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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <stdarg.h>
30 #include <unistd.h>
31 #include <limits.h>
32 #include <string.h>
33 #include <syslog.h>
34 #include <errno.h>
35 #include <locale.h>
36 #ifndef SUNOS_4
37 #include <libintl.h>
38 #endif
39 #include <pwd.h>
40 #include <alloca.h>
41
42 #include <ns.h>
43 #include <list.h>
44
45 extern char *optarg;
46 extern int optind, opterr, optopt;
47 extern char *getenv(const char *);
48
49 static void _decode_ldapResult(int result, char *printerName);
50
51 static int
authorized()52 authorized()
53 {
54 struct passwd *pw;
55 uid_t uid;
56 gid_t *list;
57 int len;
58 int maxgrp;
59
60 if ((uid = getuid()) == 0)
61 return (1); /* "root" is authorized */
62
63 if (((pw = getpwnam("lp")) != NULL) && (uid == pw->pw_uid))
64 return (1); /* "lp" is authorized */
65
66 if ((pw = getpwuid(uid)) == NULL)
67 return (0); /* intruders are not authorized */
68
69 if (chkauthattr("solaris.print.admin", pw->pw_name) == 1)
70 return (1); /* "solaris.print.admin" is authorized */
71
72 /* How many supplemental groups do we have? */
73 maxgrp = getgroups(0, NULL);
74 list = alloca(maxgrp * sizeof (gid_t));
75
76 if ((len = getgroups(maxgrp, list)) != -1)
77 while (len-- > 0)
78 if (list[len] == 14)
79 return (1); /* group 14 is authorized */
80
81 return (0); /* nobody else is authorized */
82 }
83
84 static void
Usage(char * name)85 Usage(char *name)
86 {
87 (void) fprintf(stderr,
88 gettext("Usage: %s [-n files | ldap] [-x] "
89 "[-h ldaphost] [-D binddn] [-w passwd] "
90 "[-a key=value] [-d key] (printer)\n"),
91 name);
92 exit(1);
93 }
94
95
96 /*
97 * main() calls the appropriate routine to parse the command line arguments
98 * and then calls the local remove routine, followed by the remote remove
99 * routine to remove jobs.
100 */
101 int
main(int ac,char * av[])102 main(int ac, char *av[])
103 {
104 int result = 0;
105 int delete_printer = 0;
106 int c;
107 char *program = NULL,
108 *printer = NULL,
109 *host = NULL,
110 *binddn = NULL,
111 *passwd = NULL,
112 *ins = NULL,
113 *ons = "files";
114 char **changes = NULL;
115 ns_cred_t *cred = NULL;
116 ns_printer_t *printer_obj = NULL;
117
118 (void) setlocale(LC_ALL, "");
119
120 #if !defined(TEXT_DOMAIN)
121 #define TEXT_DOMAIN "SYS_TEST"
122 #endif
123 (void) textdomain(TEXT_DOMAIN);
124
125 if ((program = strrchr(av[0], '/')) == NULL)
126 program = av[0];
127 else
128 program++;
129
130 openlog(program, LOG_PID, LOG_LPR);
131
132 if (ac < 2)
133 Usage(program);
134
135 while ((c = getopt(ac, av, "a:d:D:h:n:r:w:x")) != EOF)
136 switch (c) {
137 case 'd':
138 if (strchr(optarg, '=') != NULL)
139 Usage(program);
140 /* FALLTHRU */
141 case 'a':
142 changes = (char **)list_append((void**)changes,
143 (void *)strdup(optarg));
144 break;
145 case 'D':
146 binddn = optarg;
147 break;
148 case 'h':
149 host = optarg;
150 break;
151 case 'n':
152 ons = optarg;
153 break;
154 case 'r':
155 ins = optarg;
156 break;
157 case 'w':
158 passwd = optarg;
159 break;
160 case 'x':
161 delete_printer++;
162 break;
163 default:
164 Usage(program);
165 }
166
167 if (optind != ac-1)
168 Usage(program);
169
170 /*
171 * Check required options have been given: [ -x | [ -a | -d ]]
172 */
173 if ((changes == NULL) && (delete_printer == 0)) {
174 Usage(program);
175 }
176
177 printer = av[optind];
178
179 if (strchr(printer, ':') != NULL) {
180 (void) fprintf(stderr, gettext(
181 "POSIX-Style names are not valid destinations (%s)\n"),
182 printer);
183 return (1);
184 }
185
186 ins = normalize_ns_name(ins);
187 ons = normalize_ns_name(ons);
188 if (ins == NULL)
189 ins = ons;
190
191 /* check / set the name service for writing */
192 if (strcasecmp("user", ons) == 0) {
193 (void) setuid(getuid());
194 ons = "user";
195 } else if (strcasecmp("files", ons) == 0) {
196 if (authorized() == 0) {
197 (void) fprintf(stderr, gettext(
198 "Permission denied: not authorized\n"));
199 return (1);
200 }
201 ons = "files";
202 } else if (strcasecmp("ldap", ons) == 0) {
203 if ((cred = calloc(1, sizeof (*cred))) == NULL) {
204 (void) fprintf(stderr,
205 gettext("could not initialize credential\n"));
206 return (1);
207 }
208
209 if (binddn == NULL) {
210 (void) fprintf(stderr,
211 gettext("Distinguished Name is required.\n"));
212 return (1);
213 }
214
215 if (passwd == NULL) {
216 passwd = getpassphrase(gettext("Bind Password:"));
217 }
218
219 /*
220 * Setup LDAP bind credentials, so that it uses
221 * the default ldap port, and the NS domain for this
222 * ldapclient box. Note: passwdType is currently not
223 * used but once the ldap native function can select
224 * secure or insure password it will pass the user selected
225 * security type.
226 */
227 cred->passwd = passwd;
228 cred->passwdType = NS_PW_INSECURE; /* use default */
229 cred->binddn = binddn;
230 cred->host = host;
231 cred->port = 0; /* use default */
232 cred->domainDN = NULL; /* use default */
233
234 ons = "ldap";
235 (void) setuid(getuid());
236 } else {
237 (void) fprintf(stderr,
238 gettext("%s is not a supported name service.\n"),
239 ons);
240 return (1);
241 }
242
243 if (strcasecmp(NS_SVC_LDAP, ons) != 0) {
244
245 /* Naming Service is not LDAP */
246
247 /* get the printer object */
248 if ((printer_obj = ns_printer_get_name(printer, ins)) == NULL) {
249 if (delete_printer != 0) {
250 (void) fprintf(stderr, gettext
251 ("%s: unknown printer\n"), printer);
252 return (1);
253 }
254 if ((printer_obj = calloc(1, sizeof (*printer_obj)))
255 == NULL) {
256 (void) fprintf(stderr, gettext(
257 "could not initialize printer object\n"));
258 return (1);
259 }
260 printer_obj->name = strdup(printer);
261 }
262
263 printer_obj->source = ons;
264
265 if (cred != NULL) {
266 printer_obj->cred = cred;
267 }
268
269 /* make the changes to it */
270 while (changes != NULL && *changes != NULL) {
271 int has_equals = (strchr(*changes, '=') != NULL);
272 char *p, *key = NULL, *value = NULL;
273
274 key = *(changes++);
275
276 for (p = key; ((p != NULL) && (*p != '\0')); p++)
277 if (*p == '=') {
278 *p = '\0';
279 value = ++p;
280 break;
281 } else if (*p == '\\')
282 p++;
283
284 if ((value != NULL) && (*value == '\0'))
285 value = NULL;
286
287 if ((key != NULL) && (key[0] != '\0')) {
288 if ((value == NULL) &&
289 (ns_get_value(key, printer_obj) == NULL) &&
290 (has_equals == 0)) {
291 fprintf(stderr,
292 gettext("%s: unknown attribute\n"),
293 key);
294 result = 1;
295 } else
296 (void) ns_set_value_from_string(key, value,
297 printer_obj);
298 }
299 }
300 if (delete_printer != 0)
301 printer_obj->attributes = NULL;
302
303 /* write it back */
304 if (ns_printer_put(printer_obj) != 0) {
305 (void) fprintf(stderr,
306 gettext("Failed to write into %s database\n"),
307 ons);
308 result = 1;
309 }
310 }
311
312 else {
313 /*
314 * Naming Service is LDAP
315 *
316 * Action the request by calling ns ldap functions to
317 * add, modify or delete the printer object.
318 */
319
320 if ((printer_obj = calloc(1, sizeof (*printer_obj))) == NULL) {
321 (void) fprintf(stderr, gettext(
322 "could not initialize printer object\n"));
323 return (1);
324 }
325
326 if ((cred != NULL) && (printer_obj != NULL)) {
327 printer_obj->name = strdup(printer);
328 printer_obj->cred = cred;
329 printer_obj->cred->domainDN = NULL; /* use default */
330 printer_obj->source = ons;
331 printer_obj->nsdata = malloc(sizeof (NS_LDAPDATA));
332
333 if (printer_obj->nsdata != NULL) {
334 /*
335 * Update the LDAP directory for this printer
336 */
337
338 if (delete_printer != 0) {
339 /* Delete the printer object */
340 ((NS_LDAPDATA *)
341 (printer_obj->nsdata))->attrList
342 = NULL;
343 } else {
344 /* Add or modify the printer object */
345 ((NS_LDAPDATA *)
346 (printer_obj->nsdata))->attrList =
347 changes;
348 }
349
350 result = ns_printer_put(printer_obj);
351 if (result != 0) {
352 /* display LDAP specific message */
353 _decode_ldapResult(result, printer);
354
355 (void) fprintf(stderr, gettext(
356 "Failed to update %s database\n"), ons);
357 result = 1;
358 }
359
360 free(printer_obj->nsdata);
361 }
362
363 else {
364 _decode_ldapResult(NSL_ERR_MEMORY, NULL);
365 result = 1;
366 }
367 }
368
369 else {
370 result = 1;
371 (void) fprintf(stderr,
372 gettext("Error - no LDAP credentials\n"));
373 }
374
375 if (printer_obj != NULL) {
376 if (printer_obj->name != NULL) {
377 free(printer_obj->name);
378 }
379 free(printer_obj);
380 }
381
382 }
383
384 return (result);
385 } /* main */
386
387
388
389
390 /*
391 * *****************************************************************************
392 *
393 * Function: _decode_ldapResult()
394 *
395 * Description: Decode the ldap_put_printer specific error codes and display
396 * the appropriate error message.
397 *
398 * Parameters:
399 * Input: int result - contains the NSL_RESULT codes
400 * char *printerName - name of printer
401 * Output: None
402 *
403 * Returns: void
404 *
405 * *****************************************************************************
406 */
407
408 static void
_decode_ldapResult(int result,char * printerName)409 _decode_ldapResult(int result, char *printerName)
410
411 {
412 NSL_RESULT lresult = (NSL_RESULT)result;
413
414 /* ------------- */
415
416 switch (lresult)
417 {
418 case NSL_OK:
419 {
420 break;
421 }
422
423 case NSL_ERR_INTERNAL:
424 {
425 (void) fprintf(stderr,
426 gettext("Unexpected software error\n"));
427 break;
428 }
429
430 case NSL_ERR_ADD_FAILED:
431 {
432 (void) fprintf(stderr, "%s %s\n",
433 gettext("Failed to add printer:"), printerName);
434 break;
435 }
436
437 case NSL_ERR_MOD_FAILED:
438 {
439 (void) fprintf(stderr, "%s %s\n",
440 gettext("Failed to modify printer:"),
441 printerName);
442 break;
443 }
444
445 case NSL_ERR_DEL_FAILED:
446 {
447 (void) fprintf(stderr, "%s %s\n",
448 gettext("Failed to delete printer:"),
449 printerName);
450 break;
451 }
452
453
454 case NSL_ERR_UNKNOWN_PRINTER:
455 {
456 (void) fprintf(stderr, "%s %s\n",
457 gettext("Unknown printer:"), printerName);
458 break;
459 }
460
461 case NSL_ERR_CREDENTIALS:
462 {
463 (void) fprintf(stderr, "%s\n",
464 gettext("Missing LDAP credential information for printer:"));
465 break;
466 }
467
468 case NSL_ERR_CONNECT:
469 {
470 (void) fprintf(stderr, "%s\n",
471 gettext("Failed to connect to LDAP server"));
472 break;
473 }
474
475 case NSL_ERR_BIND:
476 {
477 (void) fprintf(stderr, gettext("LDAP bind failed\n"));
478 break;
479 }
480
481 case NSL_ERR_RENAME:
482 {
483 (void) fprintf(stderr, "%s %s\n",
484 gettext("Object rename not allowed for printer:"),
485 printerName);
486 break;
487 }
488
489 case NSL_ERR_KVP:
490 {
491 (void) fprintf(stderr, "%s",
492 gettext("Setting sun-printer-kvp attribute is "
493 "not supported through this command.\n"));
494 break;
495 }
496
497 case NSL_ERR_BSDADDR:
498 {
499 (void) fprintf(stderr, "%s",
500 gettext("Setting sun-printer-bsdaddr attribute is "
501 "not supported through this command.\n"
502 "Use the bsaddr attribute instead.\n"));
503 break;
504 }
505
506 case NSL_ERR_PNAME:
507 {
508 (void) fprintf(stderr, "%s",
509 gettext("Setting printer-name attribute is "
510 "not supported through this command.\n"));
511 break;
512 }
513
514 case NSL_ERR_MEMORY:
515 {
516 (void) fprintf(stderr,
517 gettext("Memory allocation error\n"));
518 break;
519 }
520
521 case NSL_ERR_MULTIOP:
522 {
523 (void) fprintf(stderr,
524 gettext("Delete and add operation on the "
525 "same key attribute is not allowed\n"));
526 break;
527 }
528
529 case NSL_ERR_NOTALLOWED:
530 {
531 (void) fprintf(stderr,
532 gettext("KVP attribute is not allowed\n"));
533 break;
534 }
535
536 default:
537 {
538 (void) fprintf(stderr,
539 gettext("Error code = %d\n"), result);
540 break;
541 }
542 }
543
544 } /* _decode_ldapResult */
545