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