diff options
author | jacobs <none@none> | 2006-06-22 13:28:31 -0700 |
---|---|---|
committer | jacobs <none@none> | 2006-06-22 13:28:31 -0700 |
commit | 355b4669e025ff377602b6fc7caaf30dbc218371 (patch) | |
tree | 29a740456e8d09f935e18068ce72814285fafeec /usr/src/lib/print/libprint/common/nss_ldap.c | |
parent | 5d0bc3ededb82d77f7c33d8f58e517a837ba5140 (diff) | |
download | illumos-gate-355b4669e025ff377602b6fc7caaf30dbc218371.tar.gz |
LSARC/2003/547 PAPI Print Commands
LSARC/2006/172 PAPI Print Commands Packaging Breakout
4144591 lpstat -d reports *process* default printer as *system* default printer
4299193 lp -cd <queue> <file> causes multiple -d options errors
4327963 RFE cancel on local queue should not require in.lpd
4331220 lpmove doesn't work on remote print queues
4470602 Customer wants to increase print limit of 52 files to 300
4949866 lpstat shows FAILED printers due to expanded status message
4994469 lpadmin doesn't add filter definitions for printers
6302778 RUNPATH & RPATH errors in SUNWipplu package
6314007 lpstat should report paper type list supported by a printer
6317991 lprm -Pprintername - command results in aSegmentation fault
6338002 lpsched support for PAPI is incomplete
6346505 print commands should use PAPI for service interaction (LSARC/2003/547)
6364267 psm-lpsched has replicated code
6389273 RUNPATH and RPATH failures in SUNWippcore
--HG--
rename : usr/src/cmd/lp/cmd/cancel.c => deleted_files/usr/src/cmd/lp/cmd/cancel.c
rename : usr/src/cmd/lp/cmd/comb.c => deleted_files/usr/src/cmd/lp/cmd/comb.c
rename : usr/src/cmd/lp/cmd/lp.c => deleted_files/usr/src/cmd/lp/cmd/lp.c
rename : usr/src/cmd/lp/cmd/lpc/Makefile => deleted_files/usr/src/cmd/lp/cmd/lpc/Makefile
rename : usr/src/cmd/lp/cmd/lpc/cmds.c => deleted_files/usr/src/cmd/lp/cmd/lpc/cmds.c
rename : usr/src/cmd/lp/cmd/lpc/cmdtab.c => deleted_files/usr/src/cmd/lp/cmd/lpc/cmdtab.c
rename : usr/src/cmd/lp/cmd/lpc/fatalmsg.c => deleted_files/usr/src/cmd/lp/cmd/lpc/fatalmsg.c
rename : usr/src/cmd/lp/cmd/lpc/global.c => deleted_files/usr/src/cmd/lp/cmd/lpc/global.c
rename : usr/src/cmd/lp/cmd/lpc/lpc.c => deleted_files/usr/src/cmd/lp/cmd/lpc/lpc.c
rename : usr/src/cmd/lp/cmd/lpc/lpc.h => deleted_files/usr/src/cmd/lp/cmd/lpc/lpc.h
rename : usr/src/cmd/lp/cmd/lpc/process.c => deleted_files/usr/src/cmd/lp/cmd/lpc/process.c
rename : usr/src/cmd/lp/cmd/lpc/sndrcv.c => deleted_files/usr/src/cmd/lp/cmd/lpc/sndrcv.c
rename : usr/src/cmd/lp/cmd/lpc/topq.c => deleted_files/usr/src/cmd/lp/cmd/lpc/topq.c
rename : usr/src/cmd/lp/cmd/lpmove.c => deleted_files/usr/src/cmd/lp/cmd/lpmove.c
rename : usr/src/cmd/lp/cmd/lpstat/Makefile => deleted_files/usr/src/cmd/lp/cmd/lpstat/Makefile
rename : usr/src/cmd/lp/cmd/lpstat/accept.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/accept.c
rename : usr/src/cmd/lp/cmd/lpstat/add_mounted.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/add_mounted.c
rename : usr/src/cmd/lp/cmd/lpstat/charset.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/charset.c
rename : usr/src/cmd/lp/cmd/lpstat/class.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/class.c
rename : usr/src/cmd/lp/cmd/lpstat/device.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/device.c
rename : usr/src/cmd/lp/cmd/lpstat/done.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/done.c
rename : usr/src/cmd/lp/cmd/lpstat/form.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/form.c
rename : usr/src/cmd/lp/cmd/lpstat/lpstat.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/lpstat.c
rename : usr/src/cmd/lp/cmd/lpstat/lpstat.h => deleted_files/usr/src/cmd/lp/cmd/lpstat/lpstat.h
rename : usr/src/cmd/lp/cmd/lpstat/output.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/output.c
rename : usr/src/cmd/lp/cmd/lpstat/parse.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/parse.c
rename : usr/src/cmd/lp/cmd/lpstat/printer.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/printer.c
rename : usr/src/cmd/lp/cmd/lpstat/request.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/request.c
rename : usr/src/cmd/lp/cmd/lpstat/send_message.c => deleted_files/usr/src/cmd/lp/cmd/lpstat/send_message.c
rename : usr/src/cmd/lp/lib/papi/attribute.c => deleted_files/usr/src/cmd/lp/lib/papi/attribute.c
rename : usr/src/cmd/lp/lib/papi/list.c => deleted_files/usr/src/cmd/lp/lib/papi/list.c
rename : usr/src/cmd/lp/lib/papi/papi.h => deleted_files/usr/src/cmd/lp/lib/papi/papi.h
rename : usr/src/cmd/lp/lib/papi/status.c => deleted_files/usr/src/cmd/lp/lib/papi/status.c
rename : usr/src/cmd/print/cancel/Makefile => deleted_files/usr/src/cmd/print/cancel/Makefile
rename : usr/src/cmd/print/cancel/cancel.c => deleted_files/usr/src/cmd/print/cancel/cancel.c
rename : usr/src/cmd/print/cancel/cancel_list.c => deleted_files/usr/src/cmd/print/cancel/cancel_list.c
rename : usr/src/cmd/print/cancel/cancel_list.h => deleted_files/usr/src/cmd/print/cancel/cancel_list.h
rename : usr/src/cmd/print/lp/Makefile => deleted_files/usr/src/cmd/print/lp/Makefile
rename : usr/src/cmd/print/lpmove/Makefile => deleted_files/usr/src/cmd/print/lpmove/Makefile
rename : usr/src/cmd/print/lpmove/lpmove.c => deleted_files/usr/src/cmd/print/lpmove/lpmove.c
rename : usr/src/cmd/print/lpstat/Makefile => deleted_files/usr/src/cmd/print/lpstat/Makefile
rename : usr/src/cmd/print/lpstat/bsd-functions.c => deleted_files/usr/src/cmd/print/lpstat/bsd-functions.c
rename : usr/src/cmd/print/lpstat/bsd-functions.h => deleted_files/usr/src/cmd/print/lpstat/bsd-functions.h
rename : usr/src/cmd/print/lpstat/lpstat.c => deleted_files/usr/src/cmd/print/lpstat/lpstat.c
rename : usr/src/cmd/print/lpstat/parse.h => deleted_files/usr/src/cmd/print/lpstat/parse.h
rename : usr/src/cmd/print/lpstat/parse_bsd.c => deleted_files/usr/src/cmd/print/lpstat/parse_bsd.c
rename : usr/src/cmd/print/lpstat/sysv-functions.c => deleted_files/usr/src/cmd/print/lpstat/sysv-functions.c
rename : usr/src/cmd/print/lpstat/sysv-functions.h => deleted_files/usr/src/cmd/print/lpstat/sysv-functions.h
rename : usr/src/cmd/print/scripts/accept => deleted_files/usr/src/cmd/print/scripts/accept
rename : usr/src/cmd/lp/lib/papi/mapfile-vers => usr/src/cmd/lp/lib/papi/mapfile
rename : usr/src/cmd/print/lp/cleanup.xml => usr/src/cmd/print/gateway/cleanup.xml
rename : usr/src/cmd/print/lp/print-cleanup => usr/src/cmd/print/gateway/print-cleanup
rename : usr/src/cmd/print/lp/lp.c => usr/src/cmd/print/gateway/printd.c
rename : usr/src/lib/print/job.c => usr/src/lib/print/libprint/common/job.c
rename : usr/src/lib/print/job.h => usr/src/lib/print/libprint/common/job.h
rename : usr/src/lib/print/list.c => usr/src/lib/print/libprint/common/list.c
rename : usr/src/lib/print/list.h => usr/src/lib/print/libprint/common/list.h
rename : usr/src/lib/print/llib-lprint => usr/src/lib/print/libprint/common/llib-lprint
rename : usr/src/lib/print/mapfile-vers => usr/src/lib/print/libprint/common/mapfile-vers
rename : usr/src/lib/print/misc.c => usr/src/lib/print/libprint/common/misc.c
rename : usr/src/lib/print/misc.h => usr/src/lib/print/libprint/common/misc.h
rename : usr/src/lib/print/network.c => usr/src/lib/print/libprint/common/network.c
rename : usr/src/lib/print/network.h => usr/src/lib/print/libprint/common/network.h
rename : usr/src/lib/print/ns.c => usr/src/lib/print/libprint/common/ns.c
rename : usr/src/lib/print/ns.h => usr/src/lib/print/libprint/common/ns.h
rename : usr/src/lib/print/ns_bsd_addr.c => usr/src/lib/print/libprint/common/ns_bsd_addr.c
rename : usr/src/lib/print/ns_cmn_kvp.c => usr/src/lib/print/libprint/common/ns_cmn_kvp.c
rename : usr/src/lib/print/ns_cmn_printer.c => usr/src/lib/print/libprint/common/ns_cmn_printer.c
rename : usr/src/lib/print/nss_convert.c => usr/src/lib/print/libprint/common/nss_convert.c
rename : usr/src/lib/print/nss_ldap.c => usr/src/lib/print/libprint/common/nss_ldap.c
rename : usr/src/lib/print/nss_printer.c => usr/src/lib/print/libprint/common/nss_printer.c
rename : usr/src/lib/print/nss_write.c => usr/src/lib/print/libprint/common/nss_write.c
rename : usr/src/lib/print/sunPrinter.at.conf.txt => usr/src/lib/print/libprint/common/sunPrinter.at.conf.txt
rename : usr/src/lib/print/sunPrinter.oc.conf.txt => usr/src/lib/print/libprint/common/sunPrinter.oc.conf.txt
Diffstat (limited to 'usr/src/lib/print/libprint/common/nss_ldap.c')
-rw-r--r-- | usr/src/lib/print/libprint/common/nss_ldap.c | 2478 |
1 files changed, 2478 insertions, 0 deletions
diff --git a/usr/src/lib/print/libprint/common/nss_ldap.c b/usr/src/lib/print/libprint/common/nss_ldap.c new file mode 100644 index 0000000000..887babc740 --- /dev/null +++ b/usr/src/lib/print/libprint/common/nss_ldap.c @@ -0,0 +1,2478 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <stdarg.h> +#include <fcntl.h> +#include <syslog.h> +#include <errno.h> +#include <pwd.h> +#include <libintl.h> +#include <netdb.h> /* for rcmd() */ + +#include <ns.h> +#include <list.h> +#include <misc.h> + +#define LDAP_REFERRALS +#include <lber.h> +#include <ldap.h> +#include <sys/systeminfo.h> + + +/* + * This modules contains the code required to manipulate printer objects in + * a LDAP directory for the Naming Service (NS) switch. + * It can "add", "modify" and "delete" the objects on the given ldap server + * and in the given NS domain DN, eg. "dc=mkg,dc=sun,dc=com". + * Note: printers known to the naming service are contained in the RDN + * "ou=printers" under the NS domain DN + */ + +#define PCONTAINER "ou=printers" + +/* attribute keywords */ +#define ATTR_DN "dn" +#define ATTR_OCLASS "objectClass" +#define ATTR_URI "printer-uri" +#define ATTR_PNAME "printer-name" +#define ATTR_XRISUP "printer-xri-supported" +#define ATTR_BSDADDR "sun-printer-bsdaddr" +#define ATTR_KVP "sun-printer-kvp" + +/* objectClass values */ +#define OCV_TOP "top" +#define OCV_PSERVICE "printerService" +#define OCV_SUNPRT "sunPrinter" +#define OCV_PABSTRACT "printerAbstract" + +/* xri-supported attribute value */ +#define AV_UNKNOWN "unknown" + + +/* + * LDAP objectclass atributes that the user can explicity change + */ + +static const char *nsl_attr_printerService[] = { + "printer-uri", + "printer-xri-supported", + /* Not allowed "printer-name", */ + "printer-natural-language-configured", + "printer-location", + "printer-info", + "printer-more-info", + "printer-make-and-model", + "printer-charset-configured", + "printer-charset-supported", + "printer-generated-natural-language-supported", + "printer-document-format-supported", + "printer-color-supported", + "printer-compression-supported", + "printer-pages-per-minute", + "printer-pages-per-minute-color", + "printer-finishings-supported", + "printer-number-up-supported", + "printer-sides-supported", + "printer-media-supported", + "printer-media-local-supported", + "printer-resolution-supported", + "printer-print-quality-supported", + "printer-job-priority-supported", + "printer-copies-supported", + "printer-job-k-octets-supported", + "printer-current-operator", + "printer-service-person", + "printer-delivery-orientation-supported", + "printer-stacking-order-supported", + "printer-output-features-supported", + (char *)NULL +}; + + +static const char *nsl_attr_printerIPP[] = { + "printer-ipp-versions-supported", + "printer-multiple-document-jobs-supported", + (char *)NULL +}; + +static const char *nsl_attr_sunPrinter[] = { + /* Not allowed "sun-printer-bsdaddr", */ + /* Not allowed "sun-printer-kvp", */ + (char *)NULL +}; + + +/* + * List of LDAP attributes that user is not allowed to explicitly change + */ +static const char *nsl_attr_notAllowed[] = { + ATTR_DN, + ATTR_OCLASS, /* objectclass */ + ATTR_PNAME, /* printer-name */ + ATTR_BSDADDR, + ATTR_KVP, + (char *)NULL +}; + + +static NSL_RESULT _connectToLDAP(ns_cred_t *cred, LDAP **ld); +static uchar_t *_constructPrinterDN(uchar_t *printerName, + uchar_t *domainDN, char **attrList); +static NSL_RESULT _checkPrinterExists(LDAP *ld, uchar_t *printerName, + uchar_t *domainDN, uchar_t **printerDN); +static NSL_RESULT _checkPrinterDNExists(LDAP *ld, uchar_t *objectDN); +static NSL_RESULT _checkSunPrinter(LDAP *ld, uchar_t *printerDN); +static NSL_RESULT _addNewPrinterObject(LDAP *ld, uchar_t *printerName, + uchar_t *domainDN, char **attrList); +static NSL_RESULT _modifyPrinterObject(LDAP *ld, uchar_t *printerDN, + uchar_t *printerName, uchar_t *domainDN, char **attrList); +static NSL_RESULT _checkAttributes(char **list); +static NSL_RESULT _addLDAPmodValue(LDAPMod ***attrs, char *type, char *value); +static NSL_RESULT _modLDAPmodValue(LDAPMod ***attrs, char *type, char *value); +static NSL_RESULT _constructAddLDAPMod(uchar_t *printerName, + char **attrList, LDAPMod ***attrs); +static NSL_RESULT _constructModLDAPMod(uchar_t *printerName, int sunPrinter, + char **attrList, char ***oldKVPList, LDAPMod ***attrs); +static NSL_RESULT _compareURIinDNs(uchar_t *dn1, uchar_t *dn2); +static uchar_t *_getThisNSDomainDN(void); +static int _popen(char *cmd, char *results, int size); +static int _attrInList(char *attr, const char **list); +static int _attrInLDAPList(char *attr); +static NSL_RESULT _getCurrentKVPValues(LDAP *ld, + uchar_t *objectDN, char ***list); +static void _freeList(char ***list); +static NSL_RESULT _modAttrKVP(char *value, char ***kvpList); +static NSL_RESULT _attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists); +static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp, + int *methodp, int freeit); + +/* + * ***************************************************************************** + * + * Function: ldap_put_printer() + * + * Description: Action the request to change a printer object in the LDAP + * directory DIT. The object is either added, modified or deleted + * depending on the request's attribute list. A null list indicates + * the request is a delete. + * The object's DN is constructed from the supplied domain DN and + * a check is done to see if the object exists already, if it + * doesn't exist then this is a request to add a new object + * If a URI is given in the attribute list and it is different to + * the existing printing object's DN then the request will be + * rejected. + * + * + * Parameters: + * Input: const ns_printer_t *printer + * - this structure contains the following : + * char *printerName - name of the printer + * ns_cred_t *cred - structure containing the ldap host and + * port, user, password and NS domain DN for the + * directory server to be updated. + * char **attrList - pointer to a list of attribute key values + * for the printer object. If the object does + * not already exist then this list contains the + * values for the new object, otherwise this list + * is a list of attributes to modify. For modify + * a null attribute value is a attribute delete + * request. A NULL ptr = delete the object. + * Output: None + * + * Returns: int - 0 = request actioned okay + * !0 = error - see NSL_RESULT codes + * + * ***************************************************************************** + */ + +int +ldap_put_printer(const ns_printer_t *printer) + +{ + NSL_RESULT result = NSL_OK; + NSL_RESULT printerExists = NSL_ERR_UNKNOWN_PRINTER; + LDAP *ld = NULL; + uchar_t *printerDN = NULL; + uchar_t *domainDN = NULL; + char *printerName = NULL; + ns_cred_t *cred = NULL; + char **attrList = NULL; + + /* -------- */ + + /* + * Note: the "attributes" list should be null for ldap as the attribute + * values are passed in the nsdata field + */ + + if ((printer != NULL) && + (printer->attributes == NULL) && (printer->name != NULL)) + { + /* extract required pointer values from structure */ + + printerName = printer->name; + cred = printer->cred; + if (printer->nsdata != NULL) + { + attrList = ((NS_LDAPDATA *)(printer->nsdata))->attrList; + } + + /* connect and bind to the ldap directory server */ + + result = _connectToLDAP(cred, &ld); + if ((result == NSL_OK) && (ld != NULL)) + { + /* + * check if the NS domain DN was given, if not use the + * current NS domain + */ + + if (cred->domainDN != NULL) + { + domainDN = (uchar_t *) + strdup((char *)cred->domainDN); + } + else + { + /* get DN of current domain */ + domainDN = _getThisNSDomainDN(); + } + + printerExists = + _checkPrinterExists(ld, (uchar_t *)printerName, + domainDN, &printerDN); + if (printerExists != LDAP_SUCCESS) + { + /* + * could not find the printer by printer-name, + * but there could be a non sunPrinter object + * so if the printer-uri was given check if + * an object for that exists + */ + printerDN = + _constructPrinterDN(NULL, + domainDN, attrList); + if (printerDN != NULL) + { + printerExists = _checkPrinterDNExists( + ld, printerDN); + } + } +#ifdef DEBUG +if (printerExists == NSL_OK) +{ +printf("DN found = '%s' for '%s'\n", printerDN, printerName); +} +#endif + + if (attrList == NULL) + { + /* + * a null list indicates that this is a DELETE + * object request, so if object exists delete + * it, otherwise report an error. + */ + if (printerExists == LDAP_SUCCESS) + { + result = ldap_delete_s(ld, + (char *)printerDN); + if (result != LDAP_SUCCESS) + { + result = NSL_ERR_DEL_FAILED; +#ifdef DEBUG +ldap_perror(ld, "ldap_delete_s failed"); +#endif + } + } + else + { + result = NSL_ERR_UNKNOWN_PRINTER; + } + } + else + { + /* + * if object exists then this is a + * modify request otherwise is is an add request + */ + + if (printerExists == LDAP_SUCCESS) + { + /* + * Modify the printer object to + * give it the new attribute values + * specified by the user + */ + result = + _modifyPrinterObject(ld, printerDN, + (uchar_t *)printerName, + domainDN, attrList); + } + else + { + /* + * add new printer object into the + * ldap directory with the user + * specified attribute values + */ + result = + _addNewPrinterObject(ld, + (uchar_t *)printerName, + domainDN, attrList); + } + } + + if (printerDN != NULL) + { + free(printerDN); + } + if (domainDN != NULL) + { + free(domainDN); + } + + /* disconnect from LDAP server */ + + (void) ldap_unbind(ld); + } + } + + else + { + /* no printerName given */ + result = NSL_ERR_INTERNAL; + } + + return ((int)result); +} /* ldap_put_printer */ + + + + +/* + * ***************************************************************************** + * + * Function: _connectToLDAP() + * + * Description: Setup the connection and bind to the LDAP directory server. + * The function returns the ldap connection descriptor + * + * Note: Currently the native ldap functions do not support secure + * passwords, when this is supported this function will require + * updating to allow the type passed in cred->passwdType to + * be used with the ldap_simple_bind() + * + * Parameters: + * Input: ns_cred_t *cred - structure containing the credentials (host, + * port, user and password) required to bind + * to the directory server to be updated. + * char *printerName - printer name used only for error messages + * Output: LDAP** - ldap connection descriptor pointer. NULL = failed + * + * Returns: NSL_RESULT - NSL_OK = connected okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_connectToLDAP(ns_cred_t *cred, LDAP **ld) + +{ + NSL_RESULT result = NSL_OK; + int lresult = 0; + int ldapPort = LDAP_PORT; /* default LDAP port number */ + int protoVersion = LDAP_VERSION3; + int derefOption = LDAP_DEREF_NEVER; + int referrals = 1; + char hostname[MAXHOSTNAMELEN]; + int tmpMethod = LDAP_AUTH_SIMPLE; /* temp - until its passed in */ + + /* -------- */ + + if ((ld == NULL) || (cred == NULL) || + ((cred->passwd == NULL) || (cred->binddn == NULL))) + { + result = NSL_ERR_CREDENTIALS; + } + + else + { + *ld = NULL; + + /* if host was not given then bind to local host */ + + if (cred->host != NULL) + { + (void) strlcpy(hostname, cred->host, sizeof (hostname)); + } + else + { + (void) sysinfo(SI_HOSTNAME, + hostname, sizeof (hostname)); + } + + /* initialise the connection to the ldap server */ + + if (cred->port != 0) + { + ldapPort = cred->port; + } + *ld = ldap_init(hostname, ldapPort); + if (*ld == NULL) + { + /* connection setup failed */ + result = NSL_ERR_CONNECT; +#ifdef DEBUG +(void) perror("ldap_init"); +#endif + } + else + { + /* set ldap options */ + + (void) ldap_set_option(*ld, LDAP_OPT_DEREF, + &derefOption); + (void) ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, + &protoVersion); + (void) ldap_set_option(*ld, LDAP_OPT_REFERRALS, + &referrals); + + /* bind to the user DN in the directory */ + + /* cred->passwdType is currently not supported */ + + lresult = ldap_simple_bind_s(*ld, + cred->binddn, cred->passwd); + + /* + * before doing anything else, set up the function to + * call to get authentication details if the + * ldap update function calls (eg. ldap_add_s()) get a + * "referral" (to another ldap server) from the + * original ldap server, eg. if we are trying to do + * a update on a LDAP replica server. + */ + (void) _manageReferralCredentials(*ld, + &(cred->binddn), &(cred->passwd), + &tmpMethod, -1); + ldap_set_rebind_proc(*ld, + (LDAP_REBINDPROC_CALLBACK *) + _manageReferralCredentials, NULL); + + if (lresult != LDAP_SUCCESS) + { + result = NSL_ERR_BIND; + *ld = NULL; +#ifdef DEBUG +(void) ldap_perror(*ld, "ldap_simple_bind_s"); +#endif + } + } + } + + return (result); +} /* _connectToLDAP */ + + + + + +/* + * ***************************************************************************** + * + * Function: _constructPrinterDN() + * + * Description: Construct the DN for the printer object from its name and NS + * domain DN. If the printer-uri is given in the attrList then + * that is used instead of the printerName. + * + * Parameters: + * Input: uchar_t *printerName + * uchar_t *domainDN + * char **attrList - this list is searched for printer-uri + * Output: None + * + * Returns: uchar_t* - pointer to the DN, this memory is malloced so + * must be freed using free() when finished with. + * + * ***************************************************************************** + */ + +static uchar_t * +_constructPrinterDN(uchar_t *printerName, uchar_t *domainDN, char **attrList) + +{ + uchar_t *dn = NULL; + uchar_t *uri = NULL; + char **p = NULL; + int len = 0; + + /* ------- */ + + /* first search for printer-uri in the attribute list */ + + for (p = attrList; (p != NULL) && (*p != NULL) && (uri == NULL); p++) + { + /* get length of this key word */ + + for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); + + if ((strncasecmp(*p, ATTR_URI, len) == 0) && + (strlen(*p) > len+1)) + { + uri = (uchar_t *)&((*p)[len+1]); + } + } + + + if (domainDN != NULL) { + size_t size; + + /* malloc memory for the DN and then construct it */ + + if ((uri == NULL) && (printerName != NULL)) + { + /* use the printerName for the RDN */ + + size = strlen(ATTR_URI) + + strlen((char *)printerName) + + strlen((char *)domainDN) + + strlen(PCONTAINER) + + 10; /* plus a few extra */ + + if ((dn = malloc(size)) != NULL) + (void) snprintf((char *)dn, size, "%s=%s,%s,%s", + ATTR_URI, printerName, PCONTAINER, domainDN); + } + else + if (uri != NULL) + { + /* use the URI for the RDN */ + + size = strlen(ATTR_URI) + + strlen((char *)uri) + + strlen((char *)domainDN) + + strlen(PCONTAINER) + + 10; /* plus a few extra */ + + if ((dn = malloc(size)) != NULL) + (void) snprintf((char *)dn, size, "%s=%s,%s,%s", + ATTR_URI, uri, PCONTAINER, domainDN); + } + + /* + * else + * { + * printName not given so return null + * } + */ + + } + + return (dn); /* caller must free this memory */ +} /* _constructPrinterDN */ + + + +/* + * ***************************************************************************** + * + * Function: _checkPrinterExists() + * + * Description: Check that the printer object for the printerName exists in the + * directory DIT and then extract the object's DN + * The function uses an exiting ldap connection and does a + * search for the printerName in the supplied domain DN. + * + * Parameters: + * Input: LDAP *ld - existing ldap connection descriptor + * uchar_t *printerName - printer name + * uchar_t *domainDN - DN of domain to search in + * Output: uchar_t **printerDN - DN of the printer - the caller should + * free this memory using free() + * + * Result: NSL_RESULT - NSL_OK = object exists + * + * ***************************************************************************** + */ + +static NSL_RESULT +_checkPrinterExists(LDAP *ld, uchar_t *printerName, uchar_t *domainDN, + uchar_t **printerDN) + +{ + NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; + int sresult = LDAP_NO_SUCH_OBJECT; + LDAPMessage *ldapMsg = NULL; + char *requiredAttrs[2] = { ATTR_PNAME, NULL }; + LDAPMessage *ldapEntry = NULL; + uchar_t *filter = NULL; + uchar_t *baseDN = NULL; + + /* ---------- */ + + if ((printerName != NULL) && (domainDN != NULL) && (printerDN != NULL)) + { + size_t size; + + if (printerDN != NULL) + { + *printerDN = NULL; + } + + /* search for this Printer in the directory */ + + size = (3 + strlen((char *)printerName) + strlen(ATTR_PNAME) + + 2); + + if ((filter = malloc(size)) != NULL) + (void) snprintf((char *)filter, size, "(%s=%s)", + ATTR_PNAME, (char *)printerName); + + size = (strlen((char *)domainDN) + strlen(PCONTAINER) + 5); + + if ((baseDN = malloc(size)) != NULL) + (void) snprintf((char *)baseDN, size, "%s,%s", + PCONTAINER, (char *)domainDN); + + sresult = ldap_search_s(ld, (char *)baseDN, LDAP_SCOPE_SUBTREE, + (char *)filter, requiredAttrs, 0, &ldapMsg); + if (sresult == LDAP_SUCCESS) + { + /* check that the object exists and extract its DN */ + + ldapEntry = ldap_first_entry(ld, ldapMsg); + if (ldapEntry != NULL) + { + /* object found - there should only be one */ + result = NSL_OK; + + if (printerDN != NULL) + { + *printerDN = (uchar_t *) + ldap_get_dn(ld, ldapEntry); + } + } + + (void) ldap_msgfree(ldapMsg); + } + } + + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _checkPrinterExists */ + + + + +/* + * ***************************************************************************** + * + * Function: _checkPrinterDNExists() + * + * Description: Check that the printer object for the DN exists in the + * directory DIT. + * The function uses an exiting ldap connection and does a + * search for the DN supplied. + * + * Parameters: LDAP *ld - existing ldap connection descriptor + * char *objectDN - DN to search for + * + * Result: NSL_RESULT - NSL_OK = object exists + * + * ***************************************************************************** + */ + +static NSL_RESULT +_checkPrinterDNExists(LDAP *ld, uchar_t *objectDN) + +{ + NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; + int sresult = LDAP_NO_SUCH_OBJECT; + LDAPMessage *ldapMsg; + char *requiredAttrs[2] = { ATTR_PNAME, NULL }; + LDAPMessage *ldapEntry; + + /* ---------- */ + + if ((ld != NULL) && (objectDN != NULL)) + { + /* search for this Printer in the directory */ + + sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE, + "(objectclass=*)", requiredAttrs, 0, &ldapMsg); + if (sresult == LDAP_SUCCESS) + { + /* check that the object exists */ + ldapEntry = ldap_first_entry(ld, ldapMsg); + if (ldapEntry != NULL) + { + /* object found */ + result = NSL_OK; + } + + (void) ldap_msgfree(ldapMsg); + } + } + + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _checkPrinterDNExists */ + + + + + +/* + * ***************************************************************************** + * + * Function: _checkSunPrinter() + * + * Description: Check that the printer object for the printerDN is a sunPrinter + * ie. it has the required objectclass attribute value. + * + * Parameters: + * Input: LDAP *ld - existing ldap connection descriptor + * Output: uchar_t *printerDN - DN of the printer + * + * Result: NSL_RESULT - NSL_OK = object exists and is a sunPrinter + * + * ***************************************************************************** + */ + +static NSL_RESULT +_checkSunPrinter(LDAP *ld, uchar_t *printerDN) + +{ + NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; + int sresult = LDAP_NO_SUCH_OBJECT; + char *requiredAttrs[2] = { ATTR_PNAME, NULL }; + LDAPMessage *ldapMsg = NULL; + LDAPMessage *ldapEntry = NULL; + char *filter = NULL; + + /* ---------- */ + + if ((ld != NULL) && (printerDN != NULL)) + { + size_t size; + + /* search for this Printer in the directory */ + + size = (3 + strlen(OCV_SUNPRT) + strlen(ATTR_OCLASS) + 2); + if ((filter = malloc(size)) != NULL) + (void) snprintf(filter, size, "(%s=%s)", + ATTR_OCLASS, OCV_SUNPRT); + + sresult = ldap_search_s(ld, (char *)printerDN, + LDAP_SCOPE_SUBTREE, filter, + requiredAttrs, 0, &ldapMsg); + if (sresult == LDAP_SUCCESS) + { + /* check that the printer object exists */ + + ldapEntry = ldap_first_entry(ld, ldapMsg); + if (ldapEntry != NULL) + { + /* object is a sunPrinter */ + result = NSL_OK; + } + + (void) ldap_msgfree(ldapMsg); + } + } + + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _checkSunPrinter */ + + + + + +/* + * ***************************************************************************** + * + * Function: _addNewPrinterObject() + * + * Description: For the given printerName add a printer object into the + * LDAP directory NS domain. The object is created with the + * supplied attribute values. Note: if the printer's uri is + * given that is used as the RDN otherwise the printer's + * name is used as the RDN + * + * Parameters: + * Input: LDAP *ld - existing ldap connection descriptor + * uchar_t *printerName - Name of printer to be added + * uchar_t *domainDN - DN of the domain to add the printer + * char **attrList - user specified attribute values list + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = request actioned okay + * !NSL_OK = error + * + * ***************************************************************************** + */ + +static NSL_RESULT +_addNewPrinterObject(LDAP *ld, uchar_t *printerName, + uchar_t *domainDN, char **attrList) + +{ + NSL_RESULT result = NSL_ERR_ADD_FAILED; + int lresult = 0; + uchar_t *printerDN = NULL; + LDAPMod **attrs = NULL; + + /* ---------- */ + + if ((ld != NULL) && (printerName != NULL) && (domainDN != NULL) && + (attrList != NULL) && (attrList[0] != NULL)) + { + result = _checkAttributes(attrList); + + if (result == NSL_OK) + { + /* + * construct a DN for the printer from the + * printerName and printer-uri if given. + */ + printerDN = _constructPrinterDN(printerName, + domainDN, attrList); + if (printerDN != NULL) + { + /* + * setup attribute values in an LDAPMod + * structure and then add the object + */ + result = _constructAddLDAPMod(printerName, + attrList, &attrs); + if (result == NSL_OK) + { + lresult = ldap_add_s(ld, + (char *)printerDN, attrs); + if (lresult == LDAP_SUCCESS) + { + result = NSL_OK; + } + else + { + result = NSL_ERR_ADD_FAILED; +#ifdef DEBUG +(void) ldap_perror(ld, "ldap_add_s"); +#endif + } + + (void) ldap_mods_free(attrs, 1); + } + free(printerDN); + } + + else + { + result = NSL_ERR_INTERNAL; + } + } + } + + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _addNewPrinterObject */ + + + + + + +/* + * ***************************************************************************** + * + * Function: _modifyPrinterObject() + * + * Description: Modify the given LDAP printer object to set the new attributes + * in the attribute list. If the printer's URI (specified in the + * attrList) changes the URI of the object the request is rejected. + * + * Parameters: + * Input: LDAP *ld - existing ldap connection descriptor + * uchar_t *printerDN - DN of printer object to modify + * uchar_t *printerName - Name of printer to be modified + * uchar_t *domainDN - DN of the domain the printer is in + * char **attrList - user specified attribute values list + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = object modified okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_modifyPrinterObject(LDAP *ld, uchar_t *printerDN, + uchar_t *printerName, uchar_t *domainDN, char **attrList) + +{ + NSL_RESULT result = NSL_ERR_INTERNAL; + int lresult = 0; + int sunPrinter = 0; + uchar_t *uriDN = NULL; + LDAPMod **attrs = NULL; + char **kvpList = NULL; + + /* ---------- */ + + if ((ld != NULL) && (printerDN != NULL) && (printerName != NULL) && + (domainDN != NULL) && (attrList != NULL) && (attrList[0] != NULL)) + { + result = _checkAttributes(attrList); + + if (result == NSL_OK) + { + /* + * The user may have requested that the printer object + * be given a new URI RDN, so construct a DN for the + * printer from the printerName or the printer-uri (if + * given). + */ + uriDN = _constructPrinterDN(NULL, domainDN, attrList); + + /* + * compare the 2 DNs to see if the URI has changed, + * if uriDN is null then the DN hasn't changed + */ + if ((uriDN == NULL) || ((uriDN != NULL) && + (_compareURIinDNs(printerDN, uriDN) == NSL_OK))) + { + /* + * setup the modify object LDAPMod + * structure and then do the modify + */ + + if (_checkSunPrinter(ld, printerDN) == NSL_OK) + { + sunPrinter = 1; + } + + (void) _getCurrentKVPValues(ld, + printerDN, &kvpList); + + result = _constructModLDAPMod(printerName, + sunPrinter, attrList, + &kvpList, &attrs); + _freeList(&kvpList); + + if ((result == NSL_OK) && (attrs != NULL)) + { + lresult = ldap_modify_s( + ld, (char *)printerDN, attrs); + if (lresult == LDAP_SUCCESS) + { + result = NSL_OK; + } + else + { + result = NSL_ERR_MOD_FAILED; +#ifdef DEBUG +(void) ldap_perror(ld, "ldap_modify_s"); +#endif + } + + (void) ldap_mods_free(attrs, 1); + } + } + else + { + /* + * printer-uri name change has been requested + * this is NOT allowed as it requires that + * a new printer object is created + */ + result = NSL_ERR_RENAME; /* NOT ALLOWED */ + } + + if (uriDN != NULL) + { + free(uriDN); + } + } + } + + return (result); +} /* _modifyPrinterObject */ + + + + +/* + * ***************************************************************************** + * + * Function: _checkAttributes() + * + * Description: Check that the given attribute lists does not contain any + * key words that are not allowed. + * + * Parameters: + * Input: char **list - attribute list to check + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = checked okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_checkAttributes(char **list) + +{ + NSL_RESULT result = NSL_OK; + int len = 0; + char *attr = NULL; + char **p = NULL; + + /* ------ */ + + for (p = list; (p != NULL) && (*p != NULL) && (result == NSL_OK); p++) + { + /* get length of this key word */ + + for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); + + /* check if the key word is allowed */ + + if (strncasecmp(*p, ATTR_KVP, len) == 0) + { + /* not supported through this interface */ + result = NSL_ERR_KVP; + } + else + if (strncasecmp(*p, ATTR_BSDADDR, len) == 0) + { + /* not supported through this interface */ + result = NSL_ERR_BSDADDR; + } + else + if (strncasecmp(*p, ATTR_PNAME, len) == 0) + { + /* not supported through this interface */ + result = NSL_ERR_PNAME; + } + else + { + /* check for any others */ + + attr = strdup(*p); + attr[len] = '\0'; /* terminate the key */ + + if (_attrInList(attr, nsl_attr_notAllowed)) + { + result = NSL_ERR_NOTALLOWED; + } + } + + } + + return (result); +} /* _checkAttributes */ + + + + +/* + * ***************************************************************************** + * + * Function: _addLDAPmodValue() + * + * Description: Add the given attribute and its value to the LDAPMod array. + * If this is the first entry in the array then create it. + * + * Parameters: + * Input: LDAPMod ***attrs - array to update + * char *type - attribute to add into array + * char *value - attribute value + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = added okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_addLDAPmodValue(LDAPMod ***attrs, char *type, char *value) + +{ + int i = 0; + int j = 0; + NSL_RESULT result = NSL_OK; + + /* ---------- */ + + if ((attrs != NULL) && (type != NULL) && (value != NULL)) + { +#ifdef DEBUG +printf("_addLDAPmodValue() type='%s', value='%s'\n", type, value); +#endif + /* search the existing LDAPMod array for the attribute */ + + for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++) + { + if (strcasecmp((*attrs)[i]->mod_type, type) == 0) + { + break; + } + } + + if (*attrs == NULL) + { + /* array empty so create it */ + + *attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *)); + if (*attrs != NULL) + { + i = 0; + } + else + { + result = NSL_ERR_MEMORY; + } + + } + else + if ((*attrs)[i] == NULL) + { + *attrs = (LDAPMod **) + realloc(*attrs, (i+2) * sizeof (LDAPMod *)); + if (*attrs == NULL) + { + result = NSL_ERR_MEMORY; + } + } + } + else + { + result = NSL_ERR_INTERNAL; + } + + if (result == NSL_OK) + { + if ((*attrs)[i] == NULL) + { + /* We've got a new slot. Create the new mod. */ + + (*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod)); + if ((*attrs)[i] != NULL) + { + (*attrs)[i]->mod_op = LDAP_MOD_ADD; + (*attrs)[i]->mod_type = strdup(type); + (*attrs)[i]->mod_values = (char **) + malloc(2 * sizeof (char *)); + if ((*attrs)[i]->mod_values != NULL) + { + (*attrs)[i]->mod_values[0] = + strdup(value); + (*attrs)[i]->mod_values[1] = NULL; + (*attrs)[i+1] = NULL; + } + else + { + result = NSL_ERR_MEMORY; + } + } + else + { + result = NSL_ERR_MEMORY; + } + } + + else + { + /* Found an existing entry so add value to it */ + + for (j = 0; (*attrs)[i]->mod_values[j] != NULL; j++); + + (*attrs)[i]->mod_values = + (char **)realloc((*attrs)[i]->mod_values, + (j + 2) * sizeof (char *)); + if ((*attrs)[i]->mod_values != NULL) + { + (*attrs)[i]->mod_values[j] = strdup(value); + (*attrs)[i]->mod_values[j+1] = NULL; + } + else + { + result = NSL_ERR_MEMORY; + } + } + } + + return (result); +} /* _addLDAPmodValue */ + + + + +/* + * ***************************************************************************** + * + * Function: _modLDAPmodValue() + * + * Description: Add the given attribute modify operation and its value into + * the LDAPMod array. This will either be a "replace" or a + * "delete"; value = null implies a "delete". + * If this is the first entry in the array then create it. + * + * Parameters: + * Input: LDAPMod ***attrs - array to update + * char *type - attribute to modify + * char *value - attribute value, null implies "delete" + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = added okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_modLDAPmodValue(LDAPMod ***attrs, char *type, char *value) + +{ + int i = 0; + int j = 0; + NSL_RESULT result = NSL_OK; + + /* ---------- */ + + if ((attrs != NULL) && (type != NULL)) + { +#ifdef DEBUG +if (value != NULL) +printf("_modLDAPmodValue() REPLACE type='%s', value='%s'\n", type, value); +else +printf("_modLDAPmodValue() DELETE type='%s'\n", type); +#endif + /* search the existing LDAPMod array for the attribute */ + + for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++) + { + if (strcasecmp((*attrs)[i]->mod_type, type) == 0) + { + break; + } + } + + if (*attrs == NULL) + { + /* array empty so create it */ + + *attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *)); + if (*attrs != NULL) + { + i = 0; + } + else + { + result = NSL_ERR_MEMORY; + } + + } + else + if ((*attrs)[i] == NULL) + { + /* attribute not found in array so add slot for it */ + + *attrs = (LDAPMod **) + realloc(*attrs, (i+2) * sizeof (LDAPMod *)); + if (*attrs == NULL) + { + result = NSL_ERR_MEMORY; + } + } + } + else + { + result = NSL_ERR_INTERNAL; + } + + if (result == NSL_OK) + { + if ((*attrs)[i] == NULL) + { + /* We've got a new slot. Create the new mod entry */ + + (*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod)); + if (((*attrs)[i] != NULL) && (value != NULL)) + { + /* Do an attribute replace */ + + (*attrs)[i]->mod_op = LDAP_MOD_REPLACE; + (*attrs)[i]->mod_type = strdup(type); + (*attrs)[i]->mod_values = (char **) + malloc(2 * sizeof (char *)); + if ((*attrs)[i]->mod_values != NULL) + { + (*attrs)[i]->mod_values[0] = + strdup(value); + (*attrs)[i]->mod_values[1] = NULL; + (*attrs)[i+1] = NULL; + } + else + { + result = NSL_ERR_MEMORY; + } + } + else + if ((*attrs)[i] != NULL) + { + /* value is null so do an attribute delete */ + + (*attrs)[i]->mod_op = LDAP_MOD_DELETE; + (*attrs)[i]->mod_type = strdup(type); + (*attrs)[i]->mod_values = NULL; + (*attrs)[i+1] = NULL; + } + else + { + result = NSL_ERR_MEMORY; /* malloc failed */ + } + } + + else + { + /* Found an existing entry so add value to it */ + + if (value != NULL) + { + /* add value to attribute's replace list */ + + if ((*attrs)[i]->mod_op == LDAP_MOD_REPLACE) + { + for (j = 0; + (*attrs)[i]->mod_values[j] != NULL; j++); + + (*attrs)[i]->mod_values = + (char **)realloc((*attrs)[i]->mod_values, + (j + 2) * sizeof (char *)); + if ((*attrs)[i]->mod_values != NULL) + { + (*attrs)[i]->mod_values[j] = + strdup(value); + (*attrs)[i]->mod_values[j+1] = NULL; + } + else + { + result = NSL_ERR_MEMORY; + } + } + else + { + /* Delete and replace not allowed */ + result = NSL_ERR_MULTIOP; + } + } + + else + { + /* + * attribute delete - so free any existing + * entries in the value array + */ + + (*attrs)[i]->mod_op = LDAP_MOD_DELETE; + + if ((*attrs)[i]->mod_values != NULL) + { + for (j = 0; + (*attrs)[i]->mod_values[j] != NULL; + j++) + { + free((*attrs)[i]->mod_values[j]); + } + + free((*attrs)[i]->mod_values); + (*attrs)[i]->mod_values = NULL; + } + } + } + } + + return (result); +} /* _modLDAPmodValue */ + + + + + +/* + * ***************************************************************************** + * + * Function: _constructAddLDAPMod() + * + * Description: For the given attribute list construct an + * LDAPMod array for the printer object to be added. Default + * attribute values are included. + * + * Parameters: + * Input: + * uchar_t *printerName - Name of printer to be added + * char **attrList - user specified attribute values list + * Output: LDAPMod ***attrs - pointer to the constructed array + * + * Returns: NSL_RESULT - NSL_OK = constructed okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_constructAddLDAPMod(uchar_t *printerName, char **attrList, LDAPMod ***attrs) + +{ + NSL_RESULT result = NSL_ERROR; + int len = 0; + char **p = NULL; + char *value = NULL; + char *attr = NULL; + + /* ---------- */ + + if ((printerName != NULL) && + ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL)) + { + *attrs = NULL; + + /* + * setup printer object attribute values in an LDAPMod structure + */ + result = _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_TOP); + if (result == NSL_OK) + { + /* Structural Objectclass */ + result = + _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_PSERVICE); + } + if (result == NSL_OK) + { + result = _addLDAPmodValue(attrs, + ATTR_OCLASS, OCV_PABSTRACT); + } + if (result == NSL_OK) + { + result = _addLDAPmodValue(attrs, + ATTR_OCLASS, OCV_SUNPRT); + } + if (result == NSL_OK) + { + result = _addLDAPmodValue(attrs, + ATTR_PNAME, (char *)printerName); + } + + /* + * Now work through the user supplied attribute + * values list and add them into the LDAPMod array + */ + + for (p = attrList; + (p != NULL) && (*p != NULL) && (result == NSL_OK); p++) + { + /* get length of this key word */ + + for (len = 0; + ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); + + if ((strlen(*p) > len+1)) + { + attr = strdup(*p); + attr[len] = '\0'; + value = strdup(&attr[len+1]); + + /* handle specific Key Value Pairs (KVP) */ + + if (strcasecmp(attr, NS_KEY_BSDADDR) == 0) + { + /* use LDAP attribute name */ + free(attr); + attr = strdup(ATTR_BSDADDR); + } + else + if (_attrInLDAPList(attr) == 0) + { + /* + * Non-LDAP attribute so use LDAP + * KVP attribute and the given KVP + * as the value, ie. + * sun-printer-kvp=description=printer + */ + free(attr); + attr = strdup(ATTR_KVP); + value = strdup(*p); + } + + /* add it into the LDAPMod array */ + + result = _addLDAPmodValue(attrs, attr, value); + + free(attr); + free(value); + } + } /* for */ + + if ((result != NSL_OK) && (*attrs != NULL)) + { + (void) ldap_mods_free(*attrs, 1); + attrs = NULL; + } + } + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _constructAddLDAPMod */ + + + + + + + +/* + * ***************************************************************************** + * + * Function: _constructModLDAPMod() + * + * Description: For the given modify attribute list, construct an + * LDAPMod array for the printer object to be modified + * + * Parameters: + * Input: uchar_t *printerName - name of printer to be modified + * int sunPrinter - Boolean; object is a sunPrinter + * char **attrList - user specified attribute values list + * char ***oldKVPList - current list of KVP values on object + * Output: LDAPMod ***attrs - pointer to the constructed array + * + * Returns: NSL_RESULT - NSL_OK = constructed okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_constructModLDAPMod(uchar_t *printerName, int sunPrinter, char **attrList, + char ***oldKVPList, LDAPMod ***attrs) + +{ + NSL_RESULT result = NSL_OK; + int len = 0; + int kvpUpdated = 0; + int kvpExists = 0; + char **p = NULL; + char *value = NULL; + char *attr = NULL; + + /* ---------- */ + + if ((printerName != NULL) && + ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL)) + { + *attrs = NULL; + + if ((oldKVPList != NULL) && (*oldKVPList != NULL)) + { + kvpExists = 1; + } + + if (!sunPrinter) + { + /* + * The object was previously not a sunPrinter, so + * add the required objectclass attribute value, and + * ensure it has the printername attribute. + */ + result = _addLDAPmodValue(attrs, + ATTR_OCLASS, OCV_SUNPRT); + if (result == NSL_OK) + { + result = _modLDAPmodValue(attrs, + ATTR_PNAME, (char *)printerName); + } + } + + /* + * work through the user supplied attribute + * values list and add them into the LDAPMod array depending + * on if they are a replace or delete attribute operation, + * a "null value" means delete. + */ + + for (p = attrList; + (p != NULL) && (*p != NULL) && (result == NSL_OK); p++) + { + /* get length of this key word */ + + for (len = 0; + ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); + + if ((strlen(*p) > len+1)) + { + attr = strdup(*p); + attr[len] = '\0'; + value = strdup(&attr[len+1]); + + /* handle specific Key Value Pairs (KVP) */ + + if ((_attrInLDAPList(attr) == 0) && + (strcasecmp(attr, NS_KEY_BSDADDR) != 0)) + { + /* + * Non-LDAP attribute so use LDAP + * KVP attribute and the given KVP as + * the value, ie. + * sun-printer-kvp=description=printer + */ + result = _modAttrKVP(*p, oldKVPList); + kvpUpdated = 1; + } + + else + { + if (strcasecmp(attr, NS_KEY_BSDADDR) == + 0) + { + /* + * use LDAP bsdaddr attribute + * name + */ + free(attr); + attr = strdup(ATTR_BSDADDR); + } + + /* + * else + * use the supplied attribute name + */ + + /* add it into the LDAPMod array */ + + result = _modLDAPmodValue(attrs, + attr, value); + } + + free(attr); + free(value); + } + + else + if (strlen(*p) >= 1) + { + /* handle attribute DELETE request */ + + attr = strdup(*p); + if (attr[len] == '=') + { + /* terminate "attribute=" */ + attr[len] = '\0'; + } + + /* handle specific Key Value Pairs (KVP) */ + + if (strcasecmp(attr, NS_KEY_BSDADDR) == 0) + { + /* use LDAP bsdaddr attribute name */ + result = _modLDAPmodValue(attrs, + ATTR_BSDADDR, NULL); + } + else + if (_attrInLDAPList(attr) == 0) + { + /* + * Non-LDAP kvp, so sort items + * in the kvp list + */ + result = _modAttrKVP(*p, oldKVPList); + kvpUpdated = 1; + } + else + { + result = _modLDAPmodValue(attrs, + attr, NULL); + } + + free(attr); + } + } /* for */ + + if ((result == NSL_OK) && (kvpUpdated)) + { + result = _attrAddKVP(attrs, *oldKVPList, kvpExists); + } + + if ((result != NSL_OK) && (*attrs != NULL)) + { + (void) ldap_mods_free(*attrs, 1); + *attrs = NULL; + } + } + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _constructModLDAPMod */ + + + + + + +/* + * ***************************************************************************** + * + * Function: _compareURIinDNs() + * + * Description: For the 2 given printer object DNs compare the naming part + * part of the DN (printer-uri) to see if they are the same. + * + * Note: This function only returns "compare failed" if their URI don't + * compare. Problems with the dn etc., return a good compare + * because I don't want us to create a new object for these + * + * Parameters: + * Input: uchar_t *dn1 + * uchar_t *dn2 + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = URIs are the same + * + * ***************************************************************************** + */ + +static NSL_RESULT +_compareURIinDNs(uchar_t *dn1, uchar_t *dn2) + +{ + NSL_RESULT result = NSL_OK; + uchar_t *DN1 = NULL; + uchar_t *DN2 = NULL; + char *p1 = NULL; + char *p2 = NULL; + + /* --------- */ + + if ((dn1 != NULL) && (dn2 != NULL)) + { + DN1 = (uchar_t *)strdup((char *)dn1); + DN2 = (uchar_t *)strdup((char *)dn2); + + /* terminate each string after the printer-uri */ + + p1 = strstr((char *)DN1, PCONTAINER); + /* move back to the comma */ + while ((p1 != NULL) && (*p1 != ',') && (p1 >= (char *)DN1)) + { + p1--; + } + + p2 = strstr((char *)DN2, PCONTAINER); + /* move back to the comma */ + while ((p2 != NULL) && (*p2 != ',') && (p2 >= (char *)DN2)) + { + p2--; + } + + if ((*p1 == ',') && (*p2 == ',')) + { + *p1 = '\0'; /* re-terminate it */ + *p2 = '\0'; /* re-terminate it */ + + /* do the compare */ + + /* + * Note: SHOULD really normalise the 2 DNs before + * doing the compare + */ +#ifdef DEBUG +printf("_compareURIinDNs() @1 (%s) (%s)\n", DN1, DN2); +#endif + if (strcasecmp((char *)DN1, (char *)DN2) != 0) + { + result = NSL_ERROR; + } + + } + + free(DN1); + free(DN2); + } + + return (result); +} /* _compareURIinDNs */ + + + + + + + +/* + * ***************************************************************************** + * + * Function: _getThisNSDomainDN() + * + * Description: Get the current Name Service Domain DN + * This is extracted from the result of executing ldaplist. + * + * Note: Do it this way until the NS LDAP library interface is + * made public. + * + * Parameters: + * Input: None + * Output: None + * + * Returns: uchar_t* - pointer to NS Domain DN (The caller should free this + * returned memory). + * + * ***************************************************************************** + */ + +#define LDAPLIST_D "/usr/bin/ldaplist -d 2>&1" +#define DNID "dn: " + +static uchar_t * +_getThisNSDomainDN(void) + +{ + uchar_t *domainDN = NULL; + char *cp = NULL; + char buf[BUFSIZ] = ""; + + /* --------- */ + + if (_popen(LDAPLIST_D, buf, sizeof (buf)) == 0) + { + if ((cp = strstr(buf, DNID)) != NULL) + { + cp += strlen(DNID); /* increment past "dn: " label */ + domainDN = (uchar_t *)strdup(cp); + + if ((cp = strchr((char *)domainDN, '\n')) != NULL) + { + *cp = '\0'; /* terminate it */ + } + } + } + + return (domainDN); +} /* _getThisNSDomainDN */ + + + + + +/* + * ***************************************************************************** + * + * Function: _popen() + * + * Description: General popen function. The caller should always use a full + * path cmd. + * + * Parameters: + * Input: char *cmd - command line to execute + * char *buffer - ptr to buffer to put result in + * int size - size of result buffer + * Output: None + * + * Returns: int - 0 = opened okay + * + * ***************************************************************************** + */ + +static int +_popen(char *cmd, char *buffer, int size) + +{ + int result = -1; + int rsize = 0; + FILE *fptr; + char safe_cmd[BUFSIZ]; + char linebuf[BUFSIZ]; + + /* -------- */ + + if ((cmd != NULL) && (buffer != NULL) && (size != 0)) + { + (void) strcpy(buffer, ""); + (void) strcpy(linebuf, ""); + (void) snprintf(safe_cmd, BUFSIZ, "IFS=' \t'; %s", cmd); + + if ((fptr = popen(safe_cmd, "r")) != NULL) + { + while ((fgets(linebuf, BUFSIZ, fptr) != NULL) && + (rsize < size)) + { + rsize = strlcat(buffer, linebuf, size); + if (rsize >= size) + { + /* result is too long */ + (void) memset(buffer, '\0', size); + } + } + + if (strlen(buffer) > 0) + { + result = 0; + } + + (void) pclose(fptr); + } + } + + return (result); +} /* popen */ + + +/* + * ***************************************************************************** + * + * Function: _attrInList() + * + * Description: For the given list check if the attribute is it + * + * Parameters: + * Input: char *attr - attribute to check + * char **list - list of attributes to check against + * Output: None + * + * Returns: int - TRUE = attr found in list + * + * ***************************************************************************** + */ + +static int +_attrInList(char *attr, const char **list) + +{ + int result = 0; + int j; + + /* ------- */ + + if ((attr != NULL) && (list != NULL)) + { + for (j = 0; (list[j] != NULL) && (result != 1); j++) + { + if (strcasecmp(list[j], attr) == 0) + { + result = 1; /* found */ + } + } + } + + return (result); +} /* _attrInList */ + + + + +/* + * ***************************************************************************** + * + * Function: _attrInLDAPList() + * + * Description: Checks to see if the given attribute is an LDAP printing + * attribute, ie. is either in an IPP objectclass or the + * sun printer objectclass. Note: some attributes are handled + * specifically outside this function, so are excluded from + * the lists that are checked. + * + * Parameters: + * Input: char *attr - attribute to check + * Output: None + * + * Returns: int - TRUE = attr found in list + * + * ***************************************************************************** + */ + +static int +_attrInLDAPList(char *attr) + +{ + int result = 0; + + /* ------- */ + + if (_attrInList(attr, nsl_attr_printerService)) + { + result = 1; /* in list */ + } + else + if (_attrInList(attr, nsl_attr_printerIPP)) + { + result = 1; /* in list */ + } + else + if (_attrInList(attr, nsl_attr_sunPrinter)) + { + result = 1; /* in list */ + } + + return (result); +} /* _attrInLDAPList */ + + + + +/* + * ***************************************************************************** + * + * Function: _getCurrentKVPValues() + * + * Description: For the given printer object read the current set of values + * the object has for the sun-printer-kvp (Key Value pair) + * + * Parameters: + * Input: LDAP *ld - existing ldap connection descriptor + * char *objectDN - DN to search for + * Output: char ***list - returned set of kvp values + * + * Result: NSL_RESULT - NSL_OK = object exists + * + * ***************************************************************************** + */ + +static NSL_RESULT +_getCurrentKVPValues(LDAP *ld, uchar_t *objectDN, char ***list) + +{ + NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; + int sresult = LDAP_NO_SUCH_OBJECT; + int i = 0; + LDAPMessage *ldapMsg; + char *requiredAttrs[2] = { ATTR_KVP, NULL }; + LDAPMessage *ldapEntry = NULL; + char *entryAttrib = NULL; + char **attribValues = NULL; + BerElement *berElement = NULL; + + /* ---------- */ + + if ((list != NULL) && (ld != NULL) && (objectDN != NULL)) + { + /* search for this Printer in the directory */ + + sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE, + "(objectclass=*)", requiredAttrs, 0, &ldapMsg); + if (sresult == LDAP_SUCCESS) + { + /* + * check that the object exists and extract its + * KVP attribute values + */ + ldapEntry = ldap_first_entry(ld, ldapMsg); + if (ldapEntry != NULL) + { + entryAttrib = ldap_first_attribute(ld, + ldapEntry, &berElement); + if ((entryAttrib != NULL) && + (strcasecmp(entryAttrib, ATTR_KVP) == 0)) + + { +#ifdef DEBUG +printf("Attribute: %s, its values are:\n", entryAttrib); +#endif + /* + * add each KVP value to the list + * that we will return + */ + attribValues = ldap_get_values( + ld, ldapEntry, entryAttrib); + for (i = 0; + attribValues[i] != NULL; i++) + { + *list = (char **) + list_append((void **)*list, + strdup(attribValues[i])); +#ifdef DEBUG +printf("\t%s\n", attribValues[i]); +#endif + } + (void) ldap_value_free(attribValues); + } + + if ((entryAttrib != NULL) && + (berElement != NULL)) + { + ber_free(berElement, 0); + } + + + /* object found */ + result = NSL_OK; + } + + (void) ldap_msgfree(ldapMsg); + } + } + + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _getCurrentKVPValues */ + + + +/* + * ***************************************************************************** + * + * Function: _freeList() + * + * Description: Free the list created by list_append() where the items in + * the list have been strdup'ed. + * + * Parameters: + * Input: char ***list - returned set of kvp values + * + * Result: void + * + * ***************************************************************************** + */ + +static void +_freeList(char ***list) + +{ + int i = 0; + + /* ------ */ + + if (list != NULL) + { + if (*list != NULL) + { + for (i = 0; (*list)[i] != NULL; i++) + { + free((*list)[i]); + } + free(*list); + } + + *list = NULL; + } +} /* _freeList */ + + + +/* + * ***************************************************************************** + * + * Function: _modAttrKVP() + * + * Description: Sort out the KVP attribute value list, such that this new + * value takes precidence over any existing value in the list. + * The current list is updated to remove this key, and the new + * key "value" is added to the list, eg. for + * value: bbb=ddddd + * and kvpList: + * aaa=yyyy + * bbb=zzzz + * ccc=xxxx + * the resulting kvpList is: + * aaa=yyyy + * ccc=xxxx + * bbb=ddddd + * + * Note: When all new values have been handled the function _attrAddKVP() + * must be called to add the "new list" values into the + * LDAPMod array. + * + * Parameters: + * Input: char *value - Key Value Pair to process, + * eg. aaaaa=hhhhh, where aaaaa is the key + * char ***kvpList - list of current KVP values + * Output: char ***kvpList - updated list of KVP values + * + * Returns: NSL_RESULT - NSL_OK = done okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_modAttrKVP(char *value, char ***kvpList) + +{ + NSL_RESULT result = NSL_ERR_INTERNAL; + int i = 0; + int inList = 0; + int keyDelete = 0; + char *key = NULL; + char **p = NULL; + char **newList = NULL; + + /* ------- */ + + if ((value != NULL) && (kvpList != NULL)) + { + result = NSL_OK; + + /* extract "key" from value */ + + key = strdup(value); + + for (i = 0; ((key)[i] != '=') && ((key)[i] != '\0'); i++); + key[i] = '\0'; /* terminate the key */ + + /* Is this a request to delete a "key" value */ + + if ((value[i] == '\0') || (value[i+1] == '\0')) + { + /* this is a request to delete the key */ + keyDelete = 1; + } + + if ((*kvpList != NULL) && (**kvpList != NULL)) + { + /* + * for each item in the list remove it if the keys match + */ + for (p = *kvpList; *p != NULL; p++) + { + for (i = 0; + ((*p)[i] != '=') && ((*p)[i] != '\0'); i++); + + if ((strlen(key) == i) && + (strncasecmp(*p, key, i) == 0)) + { + inList = 1; + } + else + { + /* no match so add value to new list */ + newList = (char **)list_append( + (void **)newList, + strdup(*p)); + } + } + } + + /* + * if it was not a DELETE request add the new key value into + * the newList, otherwise we have already removed the key + */ + + if (!keyDelete) + { + newList = (char **)list_append((void **)newList, + strdup(value)); + } + + if ((newList != NULL) || (inList)) + { + /* replace old list with the newList */ + _freeList(kvpList); + *kvpList = newList; + } + + free(key); + } + + return (result); +} /* modAttrKVP */ + + + + +/* + * ***************************************************************************** + * + * Function: _attrAddKVP() + * + * Description: Process KVP items in the kvpList adding them to the + * LDAPMod modify array. If the list is empty but there were + * previously LDAP KVP values delete them. + * + * Note: This function should only be called when all the new KVP + * items have been processed by _modAttrKVP() + * + * Parameters: + * Input: LDAPMod ***attrs - array to update + * char **kvpList - list KVP values + * int kvpExists - object currently has LDAP KVP values + * Output: None + * + * Returns: NSL_RESULT - NSL_OK = done okay + * + * ***************************************************************************** + */ + +static NSL_RESULT +_attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists) + +{ + NSL_RESULT result = NSL_OK; + + /* ------- */ + + if (attrs != NULL) + { + if (kvpList != NULL) + { + while ((kvpList != NULL) && (*kvpList != NULL)) + { + /* add item to LDAPMod array */ + + result = + _modLDAPmodValue(attrs, ATTR_KVP, *kvpList); + + kvpList++; + } + } + else + if (kvpExists) + { + /* + * We now have no LDAP KVP values but there were + * some previously, so delete them + */ + result = _modLDAPmodValue(attrs, ATTR_KVP, NULL); + } + } + + else + { + result = NSL_ERR_INTERNAL; + } + + return (result); +} /* _attrAddKVP */ + + + + +/* + * ***************************************************************************** + * + * Function: _manageReferralCredentials() + * + * Description: This function is called if a referral request is returned by + * the origonal LDAP server during the ldap update request call, + * eg. ldap_add_s(), ldap_modify_s() or ldap_delete_s(). + * Parameters: + * Input: LDAP *ld - LDAP descriptor + * int freeit - 0 = first call to get details + * - 1 = second call to free details + * - -1 = initial store of authentication details + * Input/Output: char **dn - returns DN to bind to on master + * char **credp - returns password for DN + * int *methodp - returns authentication type, eg. simple + * + * Returns: int - 0 = okay + * + * ***************************************************************************** + */ +static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp, + int *methodp, int freeit) + +{ + int result = 0; + static char *sDN = NULL; + static char *sPasswd = NULL; + static int sMethod = LDAP_AUTH_SIMPLE; + + /* -------- */ + + if (freeit == 1) + { + /* second call - free memory */ + + if ((dn != NULL) && (*dn != NULL)) + { + free(*dn); + } + + if ((credp != NULL) && (*credp != NULL)) + { + free(*credp); + } + } + + else + if ((ld != NULL) && + (dn != NULL) && (credp != NULL) && (methodp != NULL)) + { + if ((freeit == 0) && (sDN != NULL) && (sPasswd != NULL)) + { + /* first call - get the saved bind credentials */ + + *dn = strdup(sDN); + *credp = strdup(sPasswd); + *methodp = sMethod; + } + else + if (freeit == -1) + { + /* initial call - save the saved bind credentials */ + + sDN = *dn; + sPasswd = *credp; + sMethod = *methodp; + } + else + { + result = 1; /* error */ + } + } + else + { + result = 1; /* error */ + } + + return (result); +} /* _manageReferralCredentials */ |