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