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 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 85 Usage(char *name) 86 { 87 (void) fprintf(stderr, 88 gettext("Usage: %s [-n files | nisplus | 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 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("nisplus", ons) == 0) { 203 ons = "nisplus"; 204 } else if (strcasecmp("ldap", ons) == 0) { 205 if ((cred = calloc(1, sizeof (*cred))) == NULL) { 206 (void) fprintf(stderr, 207 gettext("could not initialize credential\n")); 208 return (1); 209 } 210 211 if (binddn == NULL) { 212 (void) fprintf(stderr, 213 gettext("Distinguished Name is required.\n")); 214 return (1); 215 } 216 217 if (passwd == NULL) { 218 passwd = getpassphrase(gettext("Bind Password:")); 219 } 220 221 /* 222 * Setup LDAP bind credentials, so that it uses 223 * the default ldap port, and the NS domain for this 224 * ldapclient box. Note: passwdType is currently not 225 * used but once the ldap native function can select 226 * secure or insure password it will pass the user selected 227 * security type. 228 */ 229 cred->passwd = passwd; 230 cred->passwdType = NS_PW_INSECURE; /* use default */ 231 cred->binddn = binddn; 232 cred->host = host; 233 cred->port = 0; /* use default */ 234 cred->domainDN = NULL; /* use default */ 235 236 ons = "ldap"; 237 (void) setuid(getuid()); 238 } else { 239 (void) fprintf(stderr, 240 gettext("%s is not a supported name service.\n"), 241 ons); 242 return (1); 243 } 244 245 if (strcasecmp(NS_SVC_LDAP, ons) != 0) { 246 247 /* Naming Service is not LDAP */ 248 249 /* get the printer object */ 250 if ((printer_obj = ns_printer_get_name(printer, ins)) == NULL) { 251 if (delete_printer != 0) { 252 (void) fprintf(stderr, gettext("%s: unknown printer\n"), 253 printer); 254 return (1); 255 } 256 if ((printer_obj = calloc(1, sizeof (*printer_obj))) == NULL) { 257 (void) fprintf(stderr, gettext( 258 "could not initialize printer object\n")); 259 return (1); 260 } 261 printer_obj->name = strdup(printer); 262 } 263 264 printer_obj->source = ons; 265 266 if (cred != NULL) { 267 printer_obj->cred = cred; 268 } 269 270 /* make the changes to it */ 271 while (changes != NULL && *changes != NULL) { 272 int has_equals = (strchr(*changes, '=') != NULL); 273 char *p, *key = NULL, *value = NULL; 274 275 key = *(changes++); 276 277 for (p = key; ((p != NULL) && (*p != NULL)); p++) 278 if (*p == '=') { 279 *p = NULL; 280 value = ++p; 281 break; 282 } else if (*p == '\\') 283 p++; 284 285 if ((value != NULL) && (*value == NULL)) 286 value = NULL; 287 288 if ((key != NULL) && (key[0] != NULL)) { 289 if ((value == NULL) && 290 (ns_get_value(key, printer_obj) == NULL) && 291 (has_equals == 0)) { 292 fprintf(stderr, 293 gettext("%s: unknown attribute\n"), 294 key); 295 result = 1; 296 } else 297 (void) ns_set_value_from_string(key, value, 298 printer_obj); 299 } 300 } 301 if (delete_printer != 0) 302 printer_obj->attributes = NULL; 303 304 /* write it back */ 305 if (ns_printer_put(printer_obj) != 0) { 306 (void) fprintf(stderr, 307 gettext("Failed to write into %s database\n"), 308 ons); 309 result = 1; 310 } 311 } 312 313 else { 314 /* 315 * Naming Service is LDAP 316 * 317 * Action the request by calling ns ldap functions to 318 * add, modify or delete the printer object. 319 */ 320 321 if ((printer_obj = calloc(1, sizeof (*printer_obj))) == NULL) { 322 (void) fprintf(stderr, gettext( 323 "could not initialize printer object\n")); 324 return (1); 325 } 326 327 if ((cred != NULL) && (printer_obj != NULL)) { 328 printer_obj->name = strdup(printer); 329 printer_obj->cred = cred; 330 printer_obj->cred->domainDN = NULL; /* use default */ 331 printer_obj->source = ons; 332 printer_obj->nsdata = malloc(sizeof (NS_LDAPDATA)); 333 334 if (printer_obj->nsdata != NULL) { 335 /* 336 * Update the LDAP directory for this printer 337 */ 338 339 if (delete_printer != 0) { 340 /* Delete the printer object */ 341 ((NS_LDAPDATA *) 342 (printer_obj->nsdata))->attrList = 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 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