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