#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdarg.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <locale.h>
#ifndef SUNOS_4
#include <libintl.h>
#endif
#include <pwd.h>
#include <alloca.h>
#include <ns.h>
#include <list.h>
extern char *optarg;
extern int optind, opterr, optopt;
extern char *getenv(const char *);
static void _decode_ldapResult(int result, char *printerName);
static int
authorized()
{
struct passwd *pw;
uid_t uid;
gid_t *list;
int len;
int maxgrp;
if ((uid = getuid()) == 0)
return (1);
if (((pw = getpwnam("lp")) != NULL) && (uid == pw->pw_uid))
return (1);
if ((pw = getpwuid(uid)) == NULL)
return (0);
if (chkauthattr("solaris.print.admin", pw->pw_name) == 1)
return (1);
maxgrp = getgroups(0, NULL);
list = alloca(maxgrp * sizeof (gid_t));
if ((len = getgroups(maxgrp, list)) != -1)
while (len-- > 0)
if (list[len] == 14)
return (1);
return (0);
}
static void
Usage(char *name)
{
(void) fprintf(stderr,
gettext("Usage: %s [-n files | ldap] [-x] "
"[-h ldaphost] [-D binddn] [-w passwd] "
"[-a key=value] [-d key] (printer)\n"),
name);
exit(1);
}
int
main(int ac, char *av[])
{
int result = 0;
int delete_printer = 0;
int c;
char *program = NULL,
*printer = NULL,
*host = NULL,
*binddn = NULL,
*passwd = NULL,
*ins = NULL,
*ons = "files";
char **changes = NULL;
ns_cred_t *cred = NULL;
ns_printer_t *printer_obj = NULL;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
if ((program = strrchr(av[0], '/')) == NULL)
program = av[0];
else
program++;
openlog(program, LOG_PID, LOG_LPR);
if (ac < 2)
Usage(program);
while ((c = getopt(ac, av, "a:d:D:h:n:r:w:x")) != EOF)
switch (c) {
case 'd':
if (strchr(optarg, '=') != NULL)
Usage(program);
case 'a':
changes = (char **)list_append((void**)changes,
(void *)strdup(optarg));
break;
case 'D':
binddn = optarg;
break;
case 'h':
host = optarg;
break;
case 'n':
ons = optarg;
break;
case 'r':
ins = optarg;
break;
case 'w':
passwd = optarg;
break;
case 'x':
delete_printer++;
break;
default:
Usage(program);
}
if (optind != ac-1)
Usage(program);
if ((changes == NULL) && (delete_printer == 0)) {
Usage(program);
}
printer = av[optind];
if (strchr(printer, ':') != NULL) {
(void) fprintf(stderr, gettext(
"POSIX-Style names are not valid destinations (%s)\n"),
printer);
return (1);
}
ins = normalize_ns_name(ins);
ons = normalize_ns_name(ons);
if (ins == NULL)
ins = ons;
if (strcasecmp("user", ons) == 0) {
(void) setuid(getuid());
ons = "user";
} else if (strcasecmp("files", ons) == 0) {
if (authorized() == 0) {
(void) fprintf(stderr, gettext(
"Permission denied: not authorized\n"));
return (1);
}
ons = "files";
} else if (strcasecmp("ldap", ons) == 0) {
if ((cred = calloc(1, sizeof (*cred))) == NULL) {
(void) fprintf(stderr,
gettext("could not initialize credential\n"));
return (1);
}
if (binddn == NULL) {
(void) fprintf(stderr,
gettext("Distinguished Name is required.\n"));
return (1);
}
if (passwd == NULL) {
passwd = getpassphrase(gettext("Bind Password:"));
}
cred->passwd = passwd;
cred->passwdType = NS_PW_INSECURE;
cred->binddn = binddn;
cred->host = host;
cred->port = 0;
cred->domainDN = NULL;
ons = "ldap";
(void) setuid(getuid());
} else {
(void) fprintf(stderr,
gettext("%s is not a supported name service.\n"),
ons);
return (1);
}
if (strcasecmp(NS_SVC_LDAP, ons) != 0) {
if ((printer_obj = ns_printer_get_name(printer, ins)) == NULL) {
if (delete_printer != 0) {
(void) fprintf(stderr, gettext
("%s: unknown printer\n"), printer);
return (1);
}
if ((printer_obj = calloc(1, sizeof (*printer_obj)))
== NULL) {
(void) fprintf(stderr, gettext(
"could not initialize printer object\n"));
return (1);
}
printer_obj->name = strdup(printer);
}
printer_obj->source = ons;
if (cred != NULL) {
printer_obj->cred = cred;
}
while (changes != NULL && *changes != NULL) {
int has_equals = (strchr(*changes, '=') != NULL);
char *p, *key = NULL, *value = NULL;
key = *(changes++);
for (p = key; ((p != NULL) && (*p != '\0')); p++)
if (*p == '=') {
*p = '\0';
value = ++p;
break;
} else if (*p == '\\')
p++;
if ((value != NULL) && (*value == '\0'))
value = NULL;
if ((key != NULL) && (key[0] != '\0')) {
if ((value == NULL) &&
(ns_get_value(key, printer_obj) == NULL) &&
(has_equals == 0)) {
fprintf(stderr,
gettext("%s: unknown attribute\n"),
key);
result = 1;
} else
(void) ns_set_value_from_string(key, value,
printer_obj);
}
}
if (delete_printer != 0)
printer_obj->attributes = NULL;
if (ns_printer_put(printer_obj) != 0) {
(void) fprintf(stderr,
gettext("Failed to write into %s database\n"),
ons);
result = 1;
}
}
else {
if ((printer_obj = calloc(1, sizeof (*printer_obj))) == NULL) {
(void) fprintf(stderr, gettext(
"could not initialize printer object\n"));
return (1);
}
if ((cred != NULL) && (printer_obj != NULL)) {
printer_obj->name = strdup(printer);
printer_obj->cred = cred;
printer_obj->cred->domainDN = NULL;
printer_obj->source = ons;
printer_obj->nsdata = malloc(sizeof (NS_LDAPDATA));
if (printer_obj->nsdata != NULL) {
if (delete_printer != 0) {
((NS_LDAPDATA *)
(printer_obj->nsdata))->attrList
= NULL;
} else {
((NS_LDAPDATA *)
(printer_obj->nsdata))->attrList =
changes;
}
result = ns_printer_put(printer_obj);
if (result != 0) {
_decode_ldapResult(result, printer);
(void) fprintf(stderr, gettext(
"Failed to update %s database\n"), ons);
result = 1;
}
free(printer_obj->nsdata);
}
else {
_decode_ldapResult(NSL_ERR_MEMORY, NULL);
result = 1;
}
}
else {
result = 1;
(void) fprintf(stderr,
gettext("Error - no LDAP credentials\n"));
}
if (printer_obj != NULL) {
if (printer_obj->name != NULL) {
free(printer_obj->name);
}
free(printer_obj);
}
}
return (result);
}
static void
_decode_ldapResult(int result, char *printerName)
{
NSL_RESULT lresult = (NSL_RESULT)result;
switch (lresult)
{
case NSL_OK:
{
break;
}
case NSL_ERR_INTERNAL:
{
(void) fprintf(stderr,
gettext("Unexpected software error\n"));
break;
}
case NSL_ERR_ADD_FAILED:
{
(void) fprintf(stderr, "%s %s\n",
gettext("Failed to add printer:"), printerName);
break;
}
case NSL_ERR_MOD_FAILED:
{
(void) fprintf(stderr, "%s %s\n",
gettext("Failed to modify printer:"),
printerName);
break;
}
case NSL_ERR_DEL_FAILED:
{
(void) fprintf(stderr, "%s %s\n",
gettext("Failed to delete printer:"),
printerName);
break;
}
case NSL_ERR_UNKNOWN_PRINTER:
{
(void) fprintf(stderr, "%s %s\n",
gettext("Unknown printer:"), printerName);
break;
}
case NSL_ERR_CREDENTIALS:
{
(void) fprintf(stderr, "%s\n",
gettext("Missing LDAP credential information for printer:"));
break;
}
case NSL_ERR_CONNECT:
{
(void) fprintf(stderr, "%s\n",
gettext("Failed to connect to LDAP server"));
break;
}
case NSL_ERR_BIND:
{
(void) fprintf(stderr, gettext("LDAP bind failed\n"));
break;
}
case NSL_ERR_RENAME:
{
(void) fprintf(stderr, "%s %s\n",
gettext("Object rename not allowed for printer:"),
printerName);
break;
}
case NSL_ERR_KVP:
{
(void) fprintf(stderr, "%s",
gettext("Setting sun-printer-kvp attribute is "
"not supported through this command.\n"));
break;
}
case NSL_ERR_BSDADDR:
{
(void) fprintf(stderr, "%s",
gettext("Setting sun-printer-bsdaddr attribute is "
"not supported through this command.\n"
"Use the bsaddr attribute instead.\n"));
break;
}
case NSL_ERR_PNAME:
{
(void) fprintf(stderr, "%s",
gettext("Setting printer-name attribute is "
"not supported through this command.\n"));
break;
}
case NSL_ERR_MEMORY:
{
(void) fprintf(stderr,
gettext("Memory allocation error\n"));
break;
}
case NSL_ERR_MULTIOP:
{
(void) fprintf(stderr,
gettext("Delete and add operation on the "
"same key attribute is not allowed\n"));
break;
}
case NSL_ERR_NOTALLOWED:
{
(void) fprintf(stderr,
gettext("KVP attribute is not allowed\n"));
break;
}
default:
{
(void) fprintf(stderr,
gettext("Error code = %d\n"), result);
break;
}
}
}