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