xref: /illumos-gate/usr/src/lib/nsswitch/ldap/common/getprinter.c (revision f012ee0c3db17469b492c2cf757226f3d7b1ebbc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #pragma weak _nss_ldap__printers_constr = _nss_ldap_printers_constr
29 
30 #include "ldap_common.h"
31 
32 static void append_attr(char *buf, char *attr);
33 
34 /* printer attributes filters */
35 #define	_F_GETPRINTERBYNAME	\
36 	"(&(objectClass=sunPrinter)(|(printer-name=%s)(printer-aliases=%s)))"
37 
38 #define	PRINTER_PREFIX	"printer-"
39 #define	SUNWPR_PREFIX	"sunwpr-"
40 
41 /*
42  * Attributes from the following classes:
43  * 	printerService
44  * 	printerAbstact
45  * 	sunPrinter
46  */
47 
48 /*
49  * Get all attributes.
50  */
51 static const char **printer_attrs = NULL;
52 
53 
54 /*
55  * _nss_ldap_printers2str is the data marshaling method for the printers
56  * getXbyY backend processes. This method is called after a successful
57  * ldap search has been performed. This method will parse the ldap search
58  * values into argp->buf.buffer. Three error conditions are expected and
59  * returned to nsswitch.
60  * In order to be compatible with old data output, the code is commented out
61  * with NSS_LDAP_PRINTERS. The NSS_LDAP_PRINTERS section is for future
62  * refrences if it's decided to fix the output format.
63  */
64 
65 static int
66 _nss_ldap_printers2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
67 {
68 	int			i, j;
69 	int			nss_result;
70 	int			buflen = 0, len;
71 	char			*buffer = NULL;
72 	char			**name, *attrname;
73 	ns_ldap_attr_t		*attr;
74 	ns_ldap_result_t	*result = be->result;
75 #ifdef	NSS_LDAP_PRINTERS
76 	int			slen, plen;
77 #endif
78 
79 	if (result == NULL)
80 		return (NSS_STR_PARSE_PARSE);
81 
82 	buflen = argp->buf.buflen;
83 	if (argp->buf.result != NULL) {
84 		be->buffer = calloc(1, buflen);
85 		if (be->buffer == NULL)
86 			return (NSS_STR_PARSE_PARSE);
87 		be->buflen = buflen;
88 		buffer = be->buffer;
89 	} else {
90 		buffer = argp->buf.buffer;
91 		(void) memset(argp->buf.buffer, 0, buflen);
92 	}
93 
94 	nss_result = NSS_STR_PARSE_SUCCESS;
95 
96 #ifdef	NSS_LDAP_PRINTERS
97 	slen = strlen(SUNWPR_PREFIX);
98 	plen = strlen(PRINTER_PREFIX);
99 #endif
100 
101 	/*
102 	 * Pick out the printer name and aliases
103 	 */
104 	name = __ns_ldap_getAttr(result->entry, "printer-name");
105 	if (name == NULL || name[0] == NULL) {
106 		nss_result = NSS_STR_PARSE_PARSE;
107 		goto result_printers2str;
108 	}
109 	len = snprintf(buffer, buflen, "%s", name[0]);
110 	TEST_AND_ADJUST(len, buffer, buflen, result_printers2str);
111 
112 #ifdef	NSS_LDAP_PRINTERS
113 	attr = __ns_ldap_getAttrStruct(result->entry, "printer-aliases");
114 	if (attr != NULL && attr->attrvalue != NULL) {
115 		for (i = 0; i < attr->value_count; i++) {
116 			len = snprintf(buffer, buflen, "|%s",
117 					attr->attrvalue[i]);
118 			TEST_AND_ADJUST(len, buffer, buflen,
119 					result_printers2str);
120 		}
121 	}
122 #endif
123 	/*
124 	 * Add the rest of the attributes
125 	 */
126 	for (i = 0; i < result->entry->attr_count; i++) {
127 		attr = getattr(result, i);
128 		if (attr == NULL) {
129 			nss_result = NSS_STR_PARSE_PARSE;
130 			goto result_printers2str;
131 		}
132 		/*
133 		 * The attribute contains key=value
134 		 */
135 		if (strcasecmp(attr->attrname, "sun-printer-kvp") == 0) {
136 			for (j = 0; j < attr->value_count; j++) {
137 				len = strlen(attr->attrvalue[j]);
138 				if (len < 1 ||
139 				    (attr->attrvalue[j] == '\0')) {
140 					*buffer = 0;
141 					nss_result = (int)NSS_STR_PARSE_PARSE;
142 					goto result_printers2str;
143 				}
144 				len =  snprintf(buffer, buflen, ":%s",
145 						attr->attrvalue[j]);
146 				TEST_AND_ADJUST(len, buffer, buflen,
147 						result_printers2str);
148 			}
149 		} else {
150 			/*
151 			 * Skip some attr names
152 			 */
153 #ifdef	NSS_LDAP_PRINTERS
154 			if (strcasecmp(attr->attrname, "printer-name") == 0 ||
155 				strcasecmp(attr->attrname, "dn") == 0 ||
156 				strcasecmp(attr->attrname,
157 					"objectclass") == 0 ||
158 				strcasecmp(attr->attrname,
159 					"printer-uri") == 0 ||
160 				strcasecmp(attr->attrname,
161 					"printer-aliases") == 0)
162 #else
163 			if (strcasecmp(attr->attrname, "printer-name") == 0)
164 #endif
165 				continue;
166 			}
167 			/*
168 			 * Translate attr name ->key name
169 			 */
170 			if (strcmp(attr->attrname, "sun-printer-bsdaddr")
171 					== 0)
172 				attrname = "bsdaddr";
173 #ifdef	NSS_LDAP_PRINTERS
174 			else if (strcmp(attr->attrname, "printer-info")
175 					== 0)
176 				attrname = "description";
177 			else if (strcmp(attr->attrname, "sunwpr-support")
178 					== 0)
179 				attrname = "itopssupported";
180 			else if (strncmp(attr->attrname, PRINTER_PREFIX, plen)
181 					== 0)
182 				attrname = attr->attrname + plen;
183 			else if (strncmp(attr->attrname, SUNWPR_PREFIX, slen)
184 					== 0)
185 				attrname = attr->attrname + slen;
186 #endif
187 			else
188 				attrname = attr->attrname;
189 
190 			/*
191 			 * The attrname is the key. The attribute
192 			 * data is the value.
193 			 */
194 			len = snprintf(buffer, buflen, ":%s=", attrname);
195 			TEST_AND_ADJUST(len, buffer, buflen,
196 					result_printers2str);
197 
198 			for (j = 0; j < attr->value_count; j++) {
199 				int k;
200 				char *kp;
201 
202 				if (attr->attrvalue[j] == NULL) {
203 					*buffer = 0;
204 					nss_result = NSS_STR_PARSE_PARSE;
205 					goto result_printers2str;
206 				}
207 				len = strlen(attr->attrvalue[j]);
208 				if (len < 1) {
209 					*buffer = 0;
210 					nss_result = NSS_STR_PARSE_PARSE;
211 					goto result_printers2str;
212 				}
213 				/*
214 				 * Add extra for any colons which need to
215 				 * be backslashed plus ending ':' or ','.
216 				 */
217 				k = 0;
218 				for (kp = attr->attrvalue[j]; *kp != NULL; kp++)
219 					if (*kp == ':')
220 						/* count ':' in value */
221 						k++;
222 				if (j == 0)
223 					/* first time */
224 					len += k;
225 				else
226 					/* add ',' */
227 					len += k + 1;
228 
229 				if (len > buflen) {
230 					nss_result = NSS_STR_PARSE_ERANGE;
231 					goto result_printers2str;
232 				}
233 				if (j > 0)
234 					*buffer++ = ',';
235 
236 				(void) append_attr(buffer,
237 					    attr->attrvalue[j]);
238 				buffer += strlen(attr->attrvalue[j]) + k;
239 				buflen -= len;
240 			}
241 	}
242 
243 	if (argp->buf.result != NULL)
244 		be->buflen = strlen(be->buffer);
245 
246 result_printers2str:
247 	(void) __ns_ldap_freeResult(&be->result);
248 	return ((int)nss_result);
249 }
250 
251 /*
252  * Attributes which contain colons must be backslashed.
253  */
254 static void
255 append_attr(char *buf, char *attr)
256 {
257 	char *cp, *bp;
258 
259 	if (strchr(attr, ':') == NULL) {
260 		(void) strcat(buf, attr);
261 		return;
262 	}
263 	bp = buf;
264 	cp = attr;
265 	while (*cp != NULL) {
266 		if (*cp == ':') {
267 			*bp++ = '\\';
268 		}
269 		*bp++ = *cp++;
270 	}
271 }
272 
273 /*
274  * getbyname gets printer attributes by printer name. This function
275  * constructs an ldap search filter using the printer name invocation
276  * parameter and the getprinterbyname search filter defined. Once the
277  * filter is constructed, we search for matching entries and marshal
278  * the data results into argp->buf.buffer for the frontend process.
279  * The function _nss_ldap_printers2str performs the data marshaling.
280  */
281 
282 static nss_status_t
283 getbyname(ldap_backend_ptr be, void *a)
284 {
285 	char		printername[BUFSIZ];
286 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
287 	char		searchfilter[SEARCHFILTERLEN];
288 
289 	(void) strncpy(printername, argp->key.name, BUFSIZ);
290 	if (snprintf(searchfilter, SEARCHFILTERLEN,
291 		_F_GETPRINTERBYNAME, printername, printername) < 0)
292 		return ((nss_status_t)NSS_NOTFOUND);
293 
294 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
295 		_PRINTERS, searchfilter, NULL, NULL, NULL));
296 }
297 
298 static ldap_backend_op_t printers_ops[] = {
299 	_nss_ldap_destr,
300 	_nss_ldap_endent,
301 	_nss_ldap_setent,
302 	_nss_ldap_getent,
303 	getbyname,
304 };
305 
306 
307 /*
308  * _nss_ldap_printers_constr is where life begins. This function calls
309  * the generic ldap constructor function to define and build the abstract
310  * data types required to support ldap operations.
311  */
312 
313 /*ARGSUSED0*/
314 nss_backend_t *
315 _nss_ldap_printers_constr(const char *dummy1, const char *dummy2,
316 			const char *dummy3)
317 {
318 
319 	return ((nss_backend_t *)_nss_ldap_constr(printers_ops,
320 		sizeof (printers_ops)/sizeof (printers_ops[0]), _PRINTERS,
321 		printer_attrs, _nss_ldap_printers2str));
322 }
323