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
_nss_ldap_printers2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)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
append_attr(char * buf,char * attr)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
getbyname(ldap_backend_ptr be,void * a)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 *
_nss_ldap_printers_constr(const char * dummy1,const char * dummy2,const char * dummy3)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