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