xref: /onnv-gate/usr/src/lib/print/libprint/common/nss_ldap.c (revision 7253:39650c3caeca)
12264Sjacobs /*
22264Sjacobs  * CDDL HEADER START
32264Sjacobs  *
42264Sjacobs  * The contents of this file are subject to the terms of the
52264Sjacobs  * Common Development and Distribution License (the "License").
62264Sjacobs  * You may not use this file except in compliance with the License.
72264Sjacobs  *
82264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs  * or http://www.opensolaris.org/os/licensing.
102264Sjacobs  * See the License for the specific language governing permissions
112264Sjacobs  * and limitations under the License.
122264Sjacobs  *
132264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs  *
192264Sjacobs  * CDDL HEADER END
202264Sjacobs  */
212264Sjacobs /*
22*7253Sjacobs  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
232264Sjacobs  * Use is subject to license terms.
242264Sjacobs  */
252264Sjacobs 
262264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
272264Sjacobs 
282264Sjacobs #include <stdio.h>
292264Sjacobs #include <stdlib.h>
302264Sjacobs #include <unistd.h>
312264Sjacobs #include <sys/types.h>
322264Sjacobs #include <sys/stat.h>
332264Sjacobs #include <string.h>
342264Sjacobs #include <stdarg.h>
352264Sjacobs #include <fcntl.h>
362264Sjacobs #include <syslog.h>
372264Sjacobs #include <errno.h>
382264Sjacobs #include <pwd.h>
392264Sjacobs #include <libintl.h>
402264Sjacobs #include <netdb.h>	/* for rcmd() */
412264Sjacobs 
422264Sjacobs #include <ns.h>
432264Sjacobs #include <list.h>
442264Sjacobs 
452264Sjacobs #define	LDAP_REFERRALS
462264Sjacobs #include <lber.h>
472264Sjacobs #include <ldap.h>
482264Sjacobs #include <sys/systeminfo.h>
492264Sjacobs 
502264Sjacobs 
512264Sjacobs /*
522264Sjacobs  * This modules contains the code required to manipulate printer objects in
532264Sjacobs  * a LDAP directory for the Naming Service (NS) switch.
542264Sjacobs  * It can "add", "modify" and "delete" the objects on the given ldap server
552264Sjacobs  * and in the given NS domain DN, eg. "dc=mkg,dc=sun,dc=com".
562264Sjacobs  * Note: printers known to the naming service are contained in the RDN
572264Sjacobs  * "ou=printers" under the NS domain DN
582264Sjacobs  */
592264Sjacobs 
602264Sjacobs #define	PCONTAINER	"ou=printers"
612264Sjacobs 
622264Sjacobs /* attribute keywords */
632264Sjacobs #define	ATTR_DN		"dn"
642264Sjacobs #define	ATTR_OCLASS	"objectClass"
652264Sjacobs #define	ATTR_URI	"printer-uri"
662264Sjacobs #define	ATTR_PNAME	"printer-name"
672264Sjacobs #define	ATTR_XRISUP	"printer-xri-supported"
682264Sjacobs #define	ATTR_BSDADDR	"sun-printer-bsdaddr"
692264Sjacobs #define	ATTR_KVP	"sun-printer-kvp"
702264Sjacobs 
712264Sjacobs /* objectClass values */
722264Sjacobs #define	OCV_TOP		"top"
732264Sjacobs #define	OCV_PSERVICE	"printerService"
742264Sjacobs #define	OCV_SUNPRT	"sunPrinter"
752264Sjacobs #define	OCV_PABSTRACT	"printerAbstract"
762264Sjacobs 
772264Sjacobs /* xri-supported attribute value */
782264Sjacobs #define	AV_UNKNOWN	"unknown"
792264Sjacobs 
802264Sjacobs 
812264Sjacobs /*
822264Sjacobs  * LDAP objectclass atributes that the user can explicity change
832264Sjacobs  */
842264Sjacobs 
852264Sjacobs static const char *nsl_attr_printerService[] = {
862264Sjacobs 	"printer-uri",
872264Sjacobs 	"printer-xri-supported",
882264Sjacobs 	/* Not allowed "printer-name", */
892264Sjacobs 	"printer-natural-language-configured",
902264Sjacobs 	"printer-location",
912264Sjacobs 	"printer-info",
922264Sjacobs 	"printer-more-info",
932264Sjacobs 	"printer-make-and-model",
942264Sjacobs 	"printer-charset-configured",
952264Sjacobs 	"printer-charset-supported",
962264Sjacobs 	"printer-generated-natural-language-supported",
972264Sjacobs 	"printer-document-format-supported",
982264Sjacobs 	"printer-color-supported",
992264Sjacobs 	"printer-compression-supported",
1002264Sjacobs 	"printer-pages-per-minute",
1012264Sjacobs 	"printer-pages-per-minute-color",
1022264Sjacobs 	"printer-finishings-supported",
1032264Sjacobs 	"printer-number-up-supported",
1042264Sjacobs 	"printer-sides-supported",
1052264Sjacobs 	"printer-media-supported",
1062264Sjacobs 	"printer-media-local-supported",
1072264Sjacobs 	"printer-resolution-supported",
1082264Sjacobs 	"printer-print-quality-supported",
1092264Sjacobs 	"printer-job-priority-supported",
1102264Sjacobs 	"printer-copies-supported",
1112264Sjacobs 	"printer-job-k-octets-supported",
1122264Sjacobs 	"printer-current-operator",
1132264Sjacobs 	"printer-service-person",
1142264Sjacobs 	"printer-delivery-orientation-supported",
1152264Sjacobs 	"printer-stacking-order-supported",
1162264Sjacobs 	"printer-output-features-supported",
1172264Sjacobs 	(char *)NULL
1182264Sjacobs };
1192264Sjacobs 
1202264Sjacobs 
1212264Sjacobs static const char *nsl_attr_printerIPP[] = {
1222264Sjacobs 	"printer-ipp-versions-supported",
1232264Sjacobs 	"printer-multiple-document-jobs-supported",
1242264Sjacobs 	(char *)NULL
1252264Sjacobs };
1262264Sjacobs 
1272264Sjacobs static const char *nsl_attr_sunPrinter[] = {
1282264Sjacobs 	/* Not allowed "sun-printer-bsdaddr", */
1292264Sjacobs 	/* Not allowed "sun-printer-kvp", */
1302264Sjacobs 	(char *)NULL
1312264Sjacobs };
1322264Sjacobs 
1332264Sjacobs 
1342264Sjacobs /*
1352264Sjacobs  * List of LDAP attributes that user is not allowed to explicitly change
1362264Sjacobs  */
1372264Sjacobs static const char *nsl_attr_notAllowed[] = {
1382264Sjacobs 	ATTR_DN,
1392264Sjacobs 	ATTR_OCLASS,		/* objectclass */
1402264Sjacobs 	ATTR_PNAME,		/* printer-name */
1412264Sjacobs 	ATTR_BSDADDR,
1422264Sjacobs 	ATTR_KVP,
1432264Sjacobs 	(char *)NULL
1442264Sjacobs };
1452264Sjacobs 
1462264Sjacobs 
1472264Sjacobs static NSL_RESULT _connectToLDAP(ns_cred_t *cred, LDAP **ld);
1482264Sjacobs static uchar_t *_constructPrinterDN(uchar_t *printerName,
1492264Sjacobs 				uchar_t *domainDN, char **attrList);
1502264Sjacobs static NSL_RESULT _checkPrinterExists(LDAP *ld, uchar_t *printerName,
1512264Sjacobs 			uchar_t *domainDN, uchar_t **printerDN);
1522264Sjacobs static NSL_RESULT _checkPrinterDNExists(LDAP *ld, uchar_t *objectDN);
1532264Sjacobs static NSL_RESULT _checkSunPrinter(LDAP *ld, uchar_t *printerDN);
1542264Sjacobs static NSL_RESULT _addNewPrinterObject(LDAP *ld, uchar_t *printerName,
1552264Sjacobs 					uchar_t *domainDN, char **attrList);
1562264Sjacobs static NSL_RESULT _modifyPrinterObject(LDAP *ld, uchar_t *printerDN,
1572264Sjacobs 		uchar_t *printerName, uchar_t *domainDN, char **attrList);
1582264Sjacobs static NSL_RESULT _checkAttributes(char **list);
1592264Sjacobs static NSL_RESULT _addLDAPmodValue(LDAPMod ***attrs, char *type, char *value);
1602264Sjacobs static NSL_RESULT _modLDAPmodValue(LDAPMod ***attrs, char *type, char *value);
1612264Sjacobs static NSL_RESULT _constructAddLDAPMod(uchar_t *printerName,
1622264Sjacobs 					char **attrList,  LDAPMod ***attrs);
1632264Sjacobs static NSL_RESULT _constructModLDAPMod(uchar_t *printerName, int sunPrinter,
1642264Sjacobs 			char **attrList, char ***oldKVPList, LDAPMod ***attrs);
1652264Sjacobs static NSL_RESULT _compareURIinDNs(uchar_t *dn1, uchar_t *dn2);
1662264Sjacobs static uchar_t *_getThisNSDomainDN(void);
1672264Sjacobs static int _popen(char *cmd, char *results, int size);
1682264Sjacobs static int _attrInList(char *attr, const char **list);
1692264Sjacobs static int _attrInLDAPList(char *attr);
1702264Sjacobs static NSL_RESULT _getCurrentKVPValues(LDAP *ld,
1712264Sjacobs 					uchar_t *objectDN, char ***list);
1722264Sjacobs static void _freeList(char ***list);
1732264Sjacobs static NSL_RESULT _modAttrKVP(char *value, char ***kvpList);
1742264Sjacobs static NSL_RESULT _attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists);
1752264Sjacobs static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp,
1762264Sjacobs 					int *methodp, int freeit);
1772264Sjacobs 
1782264Sjacobs /*
1792264Sjacobs  * *****************************************************************************
1802264Sjacobs  *
1812264Sjacobs  * Function:    ldap_put_printer()
1822264Sjacobs  *
1832264Sjacobs  * Description: Action the request to change a printer object in the LDAP
1842264Sjacobs  *              directory DIT. The object is either added, modified or deleted
1852264Sjacobs  *              depending on the request's attribute list. A null list indicates
1862264Sjacobs  *              the request is a delete.
1872264Sjacobs  *              The object's DN is constructed from the supplied domain DN and
1882264Sjacobs  *              a check is done to see if the object exists already, if it
1892264Sjacobs  *              doesn't exist then this is a request to add a new object
1902264Sjacobs  *              If a URI is given in the attribute list and it is different to
1912264Sjacobs  *              the existing printing object's DN then the request will be
1922264Sjacobs  *              rejected.
1932264Sjacobs  *
1942264Sjacobs  *
1952264Sjacobs  * Parameters:
1962264Sjacobs  * Input:       const ns_printer_t *printer
1972264Sjacobs  *                - this structure contains the following :
1982264Sjacobs  *                  char *printerName - name of the printer
1992264Sjacobs  *                  ns_cred_t *cred - structure containing the ldap host and
2002264Sjacobs  *                                port, user, password and NS domain DN for the
2012264Sjacobs  *                                directory server to be updated.
2022264Sjacobs  *                  char **attrList - pointer to a list of attribute key values
2032264Sjacobs  *                                for the printer object. If the object does
2042264Sjacobs  *                                not already exist then this list contains the
2052264Sjacobs  *                                values for the new object, otherwise this list
2062264Sjacobs  *                                is a list of attributes to modify. For modify
2072264Sjacobs  *                                a null attribute value is a attribute delete
2082264Sjacobs  *                                request. A NULL ptr = delete the object.
2092264Sjacobs  * Output:      None
2102264Sjacobs  *
2112264Sjacobs  * Returns:     int - 0 = request actioned okay
2122264Sjacobs  *                   !0 = error - see NSL_RESULT codes
2132264Sjacobs  *
2142264Sjacobs  * *****************************************************************************
2152264Sjacobs  */
2162264Sjacobs 
2172264Sjacobs int
ldap_put_printer(const ns_printer_t * printer)2182264Sjacobs ldap_put_printer(const ns_printer_t *printer)
2192264Sjacobs 
2202264Sjacobs {
2212264Sjacobs 	NSL_RESULT result = NSL_OK;
2222264Sjacobs 	NSL_RESULT printerExists = NSL_ERR_UNKNOWN_PRINTER;
2232264Sjacobs 	LDAP *ld = NULL;
2242264Sjacobs 	uchar_t *printerDN = NULL;
2252264Sjacobs 	uchar_t *domainDN = NULL;
2262264Sjacobs 	char *printerName = NULL;
2272264Sjacobs 	ns_cred_t *cred = NULL;
2282264Sjacobs 	char **attrList = NULL;
2292264Sjacobs 
2302264Sjacobs 	/* -------- */
2312264Sjacobs 
2322264Sjacobs 	/*
2332264Sjacobs 	 * Note: the "attributes" list should be null for ldap as the attribute
2342264Sjacobs 	 * values are passed in the nsdata field
2352264Sjacobs 	 */
2362264Sjacobs 
2372264Sjacobs 	if ((printer != NULL) &&
2382264Sjacobs 	    (printer->attributes == NULL) && (printer->name != NULL))
2392264Sjacobs 	{
2402264Sjacobs 		/* extract required pointer values from structure */
2412264Sjacobs 
2422264Sjacobs 		printerName = printer->name;
2432264Sjacobs 		cred = printer->cred;
2442264Sjacobs 		if (printer->nsdata != NULL)
2452264Sjacobs 		{
2462264Sjacobs 			attrList = ((NS_LDAPDATA *)(printer->nsdata))->attrList;
2472264Sjacobs 		}
2482264Sjacobs 
2492264Sjacobs 		/* connect and bind to the ldap directory server */
2502264Sjacobs 
2512264Sjacobs 		result = _connectToLDAP(cred, &ld);
2522264Sjacobs 		if ((result == NSL_OK) && (ld != NULL))
2532264Sjacobs 		{
2542264Sjacobs 			/*
2552264Sjacobs 			 * check if the NS domain DN was given, if not use the
2562264Sjacobs 			 * current NS domain
2572264Sjacobs 			 */
2582264Sjacobs 
2592264Sjacobs 			if (cred->domainDN != NULL)
2602264Sjacobs 			{
2612264Sjacobs 				domainDN = (uchar_t *)
2622264Sjacobs 					strdup((char *)cred->domainDN);
2632264Sjacobs 			}
2642264Sjacobs 			else
2652264Sjacobs 			{
2662264Sjacobs 				/* get DN of current domain */
2672264Sjacobs 				domainDN = _getThisNSDomainDN();
2682264Sjacobs 			}
2692264Sjacobs 
2702264Sjacobs 			printerExists =
2712264Sjacobs 				_checkPrinterExists(ld, (uchar_t *)printerName,
2722264Sjacobs 							domainDN, &printerDN);
2732264Sjacobs 			if (printerExists != LDAP_SUCCESS)
2742264Sjacobs 			{
2752264Sjacobs 				/*
2762264Sjacobs 				 * could not find the printer by printer-name,
2772264Sjacobs 				 * but there could be a non sunPrinter object
2782264Sjacobs 				 * so if the printer-uri was given check if
2792264Sjacobs 				 * an object for that exists
2802264Sjacobs 				 */
2812264Sjacobs 				printerDN =
2822264Sjacobs 				    _constructPrinterDN(NULL,
2832264Sjacobs 							domainDN, attrList);
2842264Sjacobs 				if (printerDN != NULL)
2852264Sjacobs 				{
2862264Sjacobs 					printerExists = _checkPrinterDNExists(
2872264Sjacobs 								ld, printerDN);
2882264Sjacobs 				}
2892264Sjacobs 			}
2902264Sjacobs #ifdef DEBUG
2912264Sjacobs if (printerExists == NSL_OK)
2922264Sjacobs {
2932264Sjacobs printf("DN found = '%s' for '%s'\n", printerDN, printerName);
2942264Sjacobs }
2952264Sjacobs #endif
2962264Sjacobs 
2972264Sjacobs 			if (attrList == NULL)
2982264Sjacobs 			{
2992264Sjacobs 				/*
3002264Sjacobs 				 * a null list indicates that this is a DELETE
3012264Sjacobs 				 * object request, so if object exists delete
3022264Sjacobs 				 * it, otherwise report an error.
3032264Sjacobs 				 */
3042264Sjacobs 				if (printerExists == LDAP_SUCCESS)
3052264Sjacobs 				{
3062264Sjacobs 				    result = ldap_delete_s(ld,
3072264Sjacobs 						(char *)printerDN);
3082264Sjacobs 				    if (result != LDAP_SUCCESS)
3092264Sjacobs 				    {
3102264Sjacobs 					result = NSL_ERR_DEL_FAILED;
3112264Sjacobs #ifdef DEBUG
3122264Sjacobs ldap_perror(ld, "ldap_delete_s failed");
3132264Sjacobs #endif
3142264Sjacobs 				    }
3152264Sjacobs 				}
3162264Sjacobs 				else
3172264Sjacobs 				{
3182264Sjacobs 				    result = NSL_ERR_UNKNOWN_PRINTER;
3192264Sjacobs 				}
3202264Sjacobs 			}
3212264Sjacobs 			else
3222264Sjacobs 			{
3232264Sjacobs 				/*
3242264Sjacobs 				 * if object exists then this is a
3252264Sjacobs 				 * modify request otherwise is is an add request
3262264Sjacobs 				 */
3272264Sjacobs 
3282264Sjacobs 				if (printerExists == LDAP_SUCCESS)
3292264Sjacobs 				{
3302264Sjacobs 					/*
3312264Sjacobs 					 * Modify the printer object to
3322264Sjacobs 					 * give it the new attribute values
3332264Sjacobs 					 * specified by the user
3342264Sjacobs 					 */
3352264Sjacobs 					result =
3362264Sjacobs 					_modifyPrinterObject(ld, printerDN,
3372264Sjacobs 						(uchar_t *)printerName,
3382264Sjacobs 						domainDN, attrList);
3392264Sjacobs 				}
3402264Sjacobs 				else
3412264Sjacobs 				{
3422264Sjacobs 					/*
3432264Sjacobs 					 * add new printer object into the
3442264Sjacobs 					 * ldap directory with the user
3452264Sjacobs 					 * specified attribute values
3462264Sjacobs 					 */
3472264Sjacobs 					result =
3482264Sjacobs 					    _addNewPrinterObject(ld,
3492264Sjacobs 						(uchar_t *)printerName,
3502264Sjacobs 						domainDN, attrList);
3512264Sjacobs 				}
3522264Sjacobs 			}
3532264Sjacobs 
3542264Sjacobs 			if (printerDN != NULL)
3552264Sjacobs 			{
3562264Sjacobs 				free(printerDN);
3572264Sjacobs 			}
3582264Sjacobs 			if (domainDN != NULL)
3592264Sjacobs 			{
3602264Sjacobs 				free(domainDN);
3612264Sjacobs 			}
3622264Sjacobs 
3632264Sjacobs 			/* disconnect from LDAP server */
3642264Sjacobs 
3652264Sjacobs 			(void) ldap_unbind(ld);
3662264Sjacobs 		}
3672264Sjacobs 	}
3682264Sjacobs 
3692264Sjacobs 	else
3702264Sjacobs 	{
3712264Sjacobs 		/* no printerName given */
3722264Sjacobs 		result = NSL_ERR_INTERNAL;
3732264Sjacobs 	}
3742264Sjacobs 
3752264Sjacobs 	return ((int)result);
3762264Sjacobs } /* ldap_put_printer */
3772264Sjacobs 
3782264Sjacobs 
3792264Sjacobs 
3802264Sjacobs 
3812264Sjacobs /*
3822264Sjacobs  * *****************************************************************************
3832264Sjacobs  *
3842264Sjacobs  * Function:    _connectToLDAP()
3852264Sjacobs  *
3862264Sjacobs  * Description: Setup the connection and bind to the LDAP directory server.
3872264Sjacobs  *              The function returns the ldap connection descriptor
3882264Sjacobs  *
3892264Sjacobs  * Note:        Currently the native ldap functions do not support secure
3902264Sjacobs  *              passwords, when this is supported this function will require
3912264Sjacobs  *              updating to allow the type passed in cred->passwdType to
3922264Sjacobs  *              be used with the ldap_simple_bind()
3932264Sjacobs  *
3942264Sjacobs  * Parameters:
3952264Sjacobs  * Input:       ns_cred_t *cred - structure containing the credentials (host,
3962264Sjacobs  *                                port, user and password) required to bind
3972264Sjacobs  *                                to the directory server to be updated.
3982264Sjacobs  *              char *printerName - printer name used only for error messages
3992264Sjacobs  * Output:      LDAP** - ldap connection descriptor pointer. NULL = failed
4002264Sjacobs  *
4012264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = connected okay
4022264Sjacobs  *
4032264Sjacobs  * *****************************************************************************
4042264Sjacobs  */
4052264Sjacobs 
4062264Sjacobs static NSL_RESULT
_connectToLDAP(ns_cred_t * cred,LDAP ** ld)4072264Sjacobs _connectToLDAP(ns_cred_t *cred, LDAP **ld)
4082264Sjacobs 
4092264Sjacobs {
4102264Sjacobs 	NSL_RESULT result = NSL_OK;
4112264Sjacobs 	int lresult = 0;
4122264Sjacobs 	int ldapPort = LDAP_PORT;	/* default LDAP port number */
4132264Sjacobs 	int protoVersion = LDAP_VERSION3;
4142264Sjacobs 	int derefOption = LDAP_DEREF_NEVER;
4152264Sjacobs 	int referrals = 1;
4162264Sjacobs 	char hostname[MAXHOSTNAMELEN];
4172264Sjacobs 	int tmpMethod = LDAP_AUTH_SIMPLE; /* temp - until its passed in */
4182264Sjacobs 
4192264Sjacobs 	/* -------- */
4202264Sjacobs 
4212264Sjacobs 	if ((ld == NULL) || (cred == NULL) ||
4222264Sjacobs 		((cred->passwd == NULL) || (cred->binddn == NULL)))
4232264Sjacobs 	{
4242264Sjacobs 		result = NSL_ERR_CREDENTIALS;
4252264Sjacobs 	}
4262264Sjacobs 
4272264Sjacobs 	else
4282264Sjacobs 	{
4292264Sjacobs 		*ld = NULL;
4302264Sjacobs 
4312264Sjacobs 		/* if host was not given then bind to local host */
4322264Sjacobs 
4332264Sjacobs 		if (cred->host != NULL)
4342264Sjacobs 		{
4352264Sjacobs 			(void) strlcpy(hostname, cred->host, sizeof (hostname));
4362264Sjacobs 		}
4372264Sjacobs 		else
4382264Sjacobs 		{
4392264Sjacobs 			(void) sysinfo(SI_HOSTNAME,
4402264Sjacobs 					hostname, sizeof (hostname));
4412264Sjacobs 		}
4422264Sjacobs 
4432264Sjacobs 		/* initialise the connection to the ldap server */
4442264Sjacobs 
4452264Sjacobs 		if (cred->port != 0)
4462264Sjacobs 		{
4472264Sjacobs 			ldapPort = cred->port;
4482264Sjacobs 		}
4492264Sjacobs 		*ld = ldap_init(hostname, ldapPort);
4502264Sjacobs 		if (*ld == NULL)
4512264Sjacobs 		{
4522264Sjacobs 			/* connection setup failed */
4532264Sjacobs 			result = NSL_ERR_CONNECT;
4542264Sjacobs #ifdef DEBUG
4552264Sjacobs (void) perror("ldap_init");
4562264Sjacobs #endif
4572264Sjacobs 		}
4582264Sjacobs 		else
4592264Sjacobs 		{
4602264Sjacobs 			/* set ldap options */
4612264Sjacobs 
4622264Sjacobs 			(void) ldap_set_option(*ld, LDAP_OPT_DEREF,
4632264Sjacobs 						&derefOption);
4642264Sjacobs 			(void) ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION,
4652264Sjacobs 						&protoVersion);
4662264Sjacobs 			(void) ldap_set_option(*ld, LDAP_OPT_REFERRALS,
4672264Sjacobs 						&referrals);
4682264Sjacobs 
4692264Sjacobs 			/* bind to the user DN in the directory */
4702264Sjacobs 
4712264Sjacobs 			/* cred->passwdType is currently not supported */
4722264Sjacobs 
4732264Sjacobs 			lresult = ldap_simple_bind_s(*ld,
4742264Sjacobs 						cred->binddn, cred->passwd);
4752264Sjacobs 
4762264Sjacobs 			/*
4772264Sjacobs 			 * before doing anything else, set up the function to
4782264Sjacobs 			 * call to get authentication details if the
4792264Sjacobs 			 * ldap update function calls (eg. ldap_add_s()) get a
4802264Sjacobs 			 * "referral" (to another ldap server) from the
4812264Sjacobs 			 * original ldap server, eg. if we are trying to do
4822264Sjacobs 			 * a update on a LDAP replica server.
4832264Sjacobs 			 */
4842264Sjacobs 			(void) _manageReferralCredentials(*ld,
4852264Sjacobs 					&(cred->binddn), &(cred->passwd),
4862264Sjacobs 					&tmpMethod, -1);
4872264Sjacobs 			ldap_set_rebind_proc(*ld,
4882264Sjacobs 			    (LDAP_REBINDPROC_CALLBACK *)
4892264Sjacobs 				_manageReferralCredentials, NULL);
4902264Sjacobs 
4912264Sjacobs 			if (lresult != LDAP_SUCCESS)
4922264Sjacobs 			{
4932264Sjacobs 				result = NSL_ERR_BIND;
4942264Sjacobs 				*ld = NULL;
4952264Sjacobs #ifdef DEBUG
4962264Sjacobs (void) ldap_perror(*ld, "ldap_simple_bind_s");
4972264Sjacobs #endif
4982264Sjacobs 			}
4992264Sjacobs 		}
5002264Sjacobs 	}
5012264Sjacobs 
5022264Sjacobs 	return (result);
5032264Sjacobs } /* _connectToLDAP */
5042264Sjacobs 
5052264Sjacobs 
5062264Sjacobs 
5072264Sjacobs 
5082264Sjacobs 
5092264Sjacobs /*
5102264Sjacobs  * *****************************************************************************
5112264Sjacobs  *
5122264Sjacobs  * Function:    _constructPrinterDN()
5132264Sjacobs  *
5142264Sjacobs  * Description: Construct the DN for the printer object from its name and NS
5152264Sjacobs  *              domain DN. If the printer-uri is given in the attrList then
5162264Sjacobs  *              that is used instead of the printerName.
5172264Sjacobs  *
5182264Sjacobs  * Parameters:
5192264Sjacobs  * Input:       uchar_t *printerName
5202264Sjacobs  *              uchar_t *domainDN
5212264Sjacobs  *              char **attrList - this list is searched for printer-uri
5222264Sjacobs  * Output:      None
5232264Sjacobs  *
5242264Sjacobs  * Returns:     uchar_t* - pointer to the DN, this memory is malloced so
5252264Sjacobs  *                         must be freed using free() when finished with.
5262264Sjacobs  *
5272264Sjacobs  * *****************************************************************************
5282264Sjacobs  */
5292264Sjacobs 
5302264Sjacobs static uchar_t *
_constructPrinterDN(uchar_t * printerName,uchar_t * domainDN,char ** attrList)5312264Sjacobs _constructPrinterDN(uchar_t *printerName, uchar_t *domainDN, char **attrList)
5322264Sjacobs 
5332264Sjacobs {
5342264Sjacobs 	uchar_t *dn = NULL;
5352264Sjacobs 	uchar_t *uri = NULL;
5362264Sjacobs 	char **p = NULL;
5372264Sjacobs 	int len = 0;
5382264Sjacobs 
5392264Sjacobs 	/* ------- */
5402264Sjacobs 
5412264Sjacobs 	/* first search for printer-uri in the attribute list */
5422264Sjacobs 
5432264Sjacobs 	for (p = attrList; (p != NULL) && (*p != NULL) && (uri == NULL); p++)
5442264Sjacobs 	{
5452264Sjacobs 		/* get length of this key word */
5462264Sjacobs 
5472264Sjacobs 		for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
5482264Sjacobs 
5492264Sjacobs 		if ((strncasecmp(*p, ATTR_URI, len) == 0) &&
5502264Sjacobs 		    (strlen(*p) > len+1))
5512264Sjacobs 		{
5522264Sjacobs 			uri = (uchar_t *)&((*p)[len+1]);
5532264Sjacobs 		}
5542264Sjacobs 	}
5552264Sjacobs 
5562264Sjacobs 
5572264Sjacobs 	if (domainDN != NULL) {
5582264Sjacobs 		size_t size;
5592264Sjacobs 
5602264Sjacobs 		/* malloc memory for the DN and then construct it */
5612264Sjacobs 
5622264Sjacobs 		if ((uri == NULL) && (printerName != NULL))
5632264Sjacobs 		{
5642264Sjacobs 			/* use the printerName for the RDN */
5652264Sjacobs 
5662264Sjacobs 			size = strlen(ATTR_URI) +
5672264Sjacobs 			    strlen((char *)printerName) +
5682264Sjacobs 			    strlen((char *)domainDN) +
5692264Sjacobs 			    strlen(PCONTAINER) +
5702264Sjacobs 			    10; /* plus a few extra */
5712264Sjacobs 
5722264Sjacobs 			if ((dn = malloc(size)) != NULL)
5732264Sjacobs 				(void) snprintf((char *)dn, size, "%s=%s,%s,%s",
5742264Sjacobs 				ATTR_URI, printerName, PCONTAINER, domainDN);
5752264Sjacobs 		}
5762264Sjacobs 		else
5772264Sjacobs 		if (uri != NULL)
5782264Sjacobs 		{
5792264Sjacobs 			/* use the URI for the RDN */
5802264Sjacobs 
5812264Sjacobs 			size = strlen(ATTR_URI) +
5822264Sjacobs 			    strlen((char *)uri) +
5832264Sjacobs 			    strlen((char *)domainDN) +
5842264Sjacobs 			    strlen(PCONTAINER) +
5852264Sjacobs 			    10; /* plus a few extra */
5862264Sjacobs 
5872264Sjacobs 			if ((dn = malloc(size)) != NULL)
5882264Sjacobs 				(void) snprintf((char *)dn, size, "%s=%s,%s,%s",
5892264Sjacobs 				ATTR_URI, uri, PCONTAINER, domainDN);
5902264Sjacobs 		}
5912264Sjacobs 
5922264Sjacobs 		/*
5932264Sjacobs 		 * else
5942264Sjacobs 		 * {
5952264Sjacobs 		 *    printName not given so return null
5962264Sjacobs 		 * }
5972264Sjacobs 		 */
5982264Sjacobs 
5992264Sjacobs 	}
6002264Sjacobs 
6012264Sjacobs 	return (dn);	/* caller must free this memory */
6022264Sjacobs } /* _constructPrinterDN */
6032264Sjacobs 
6042264Sjacobs 
6052264Sjacobs 
6062264Sjacobs /*
6072264Sjacobs  * *****************************************************************************
6082264Sjacobs  *
6092264Sjacobs  * Function:    _checkPrinterExists()
6102264Sjacobs  *
6112264Sjacobs  * Description: Check that the printer object for the printerName exists in the
6122264Sjacobs  *              directory DIT and then extract the object's DN
6132264Sjacobs  *              The function uses an exiting ldap connection and does a
6142264Sjacobs  *              search for the printerName in the supplied domain DN.
6152264Sjacobs  *
6162264Sjacobs  * Parameters:
6172264Sjacobs  * Input:       LDAP *ld             - existing ldap connection descriptor
6182264Sjacobs  *              uchar_t *printerName - printer name
6192264Sjacobs  *              uchar_t *domainDN    - DN of domain to search in
6202264Sjacobs  * Output:      uchar_t **printerDN  - DN of the printer - the caller should
6212264Sjacobs  *                                     free this memory using free()
6222264Sjacobs  *
6232264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists
6242264Sjacobs  *
6252264Sjacobs  * *****************************************************************************
6262264Sjacobs  */
6272264Sjacobs 
6282264Sjacobs static NSL_RESULT
_checkPrinterExists(LDAP * ld,uchar_t * printerName,uchar_t * domainDN,uchar_t ** printerDN)6292264Sjacobs _checkPrinterExists(LDAP *ld, uchar_t *printerName, uchar_t *domainDN,
6302264Sjacobs 			uchar_t **printerDN)
6312264Sjacobs 
6322264Sjacobs {
6332264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
6342264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
6352264Sjacobs 	LDAPMessage *ldapMsg = NULL;
6362264Sjacobs 	char *requiredAttrs[2] = { ATTR_PNAME, NULL };
6372264Sjacobs 	LDAPMessage *ldapEntry = NULL;
6382264Sjacobs 	uchar_t *filter = NULL;
6392264Sjacobs 	uchar_t *baseDN = NULL;
6402264Sjacobs 
6412264Sjacobs 	/* ---------- */
6422264Sjacobs 
6432264Sjacobs 	if ((printerName != NULL) && (domainDN != NULL) && (printerDN != NULL))
6442264Sjacobs 	{
6452264Sjacobs 		size_t size;
6462264Sjacobs 
6472264Sjacobs 		if (printerDN != NULL)
6482264Sjacobs 		{
6492264Sjacobs 			*printerDN = NULL;
6502264Sjacobs 		}
6512264Sjacobs 
6522264Sjacobs 		/* search for this Printer in the directory */
6532264Sjacobs 
6542264Sjacobs 		size = (3 + strlen((char *)printerName) + strlen(ATTR_PNAME) +
6552264Sjacobs 			2);
6562264Sjacobs 
6572264Sjacobs 		if ((filter = malloc(size)) != NULL)
6582264Sjacobs 			(void) snprintf((char *)filter, size, "(%s=%s)",
6592264Sjacobs 			    ATTR_PNAME, (char *)printerName);
6602264Sjacobs 
6612264Sjacobs 		size = (strlen((char *)domainDN) + strlen(PCONTAINER) + 5);
6622264Sjacobs 
6632264Sjacobs 		if ((baseDN = malloc(size)) != NULL)
6642264Sjacobs 			(void) snprintf((char *)baseDN, size, "%s,%s",
6652264Sjacobs 			    PCONTAINER, (char *)domainDN);
6662264Sjacobs 
6672264Sjacobs 		sresult = ldap_search_s(ld, (char *)baseDN, LDAP_SCOPE_SUBTREE,
6682264Sjacobs 				(char *)filter, requiredAttrs, 0, &ldapMsg);
6692264Sjacobs 		if (sresult == LDAP_SUCCESS)
6702264Sjacobs 		{
6712264Sjacobs 			/* check that the object exists and extract its DN */
6722264Sjacobs 
6732264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
6742264Sjacobs 			if (ldapEntry != NULL)
6752264Sjacobs 			{
6762264Sjacobs 				/* object found - there should only be one */
6772264Sjacobs 				result = NSL_OK;
6782264Sjacobs 
6792264Sjacobs 				if (printerDN != NULL)
6802264Sjacobs 				{
6812264Sjacobs 					*printerDN = (uchar_t *)
6822264Sjacobs 						ldap_get_dn(ld, ldapEntry);
6832264Sjacobs 				}
6842264Sjacobs 			}
6852264Sjacobs 
6862264Sjacobs 			(void) ldap_msgfree(ldapMsg);
6872264Sjacobs 		}
6882264Sjacobs 	}
6892264Sjacobs 
6902264Sjacobs 	else
6912264Sjacobs 	{
6922264Sjacobs 		result = NSL_ERR_INTERNAL;
6932264Sjacobs 	}
6942264Sjacobs 
6952264Sjacobs 	return (result);
6962264Sjacobs } /* _checkPrinterExists */
6972264Sjacobs 
6982264Sjacobs 
6992264Sjacobs 
7002264Sjacobs 
7012264Sjacobs /*
7022264Sjacobs  * *****************************************************************************
7032264Sjacobs  *
7042264Sjacobs  * Function:    _checkPrinterDNExists()
7052264Sjacobs  *
7062264Sjacobs  * Description: Check that the printer object for the DN exists in the
7072264Sjacobs  *              directory DIT.
7082264Sjacobs  *              The function uses an exiting ldap connection and does a
7092264Sjacobs  *              search for the DN supplied.
7102264Sjacobs  *
7112264Sjacobs  * Parameters:  LDAP *ld       - existing ldap connection descriptor
7122264Sjacobs  *              char *objectDN - DN to search for
7132264Sjacobs  *
7142264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists
7152264Sjacobs  *
7162264Sjacobs  * *****************************************************************************
7172264Sjacobs  */
7182264Sjacobs 
7192264Sjacobs static NSL_RESULT
_checkPrinterDNExists(LDAP * ld,uchar_t * objectDN)7202264Sjacobs _checkPrinterDNExists(LDAP *ld, uchar_t *objectDN)
7212264Sjacobs 
7222264Sjacobs {
7232264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
7242264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
7252264Sjacobs 	LDAPMessage *ldapMsg;
7262264Sjacobs 	char *requiredAttrs[2] = { ATTR_PNAME, NULL };
7272264Sjacobs 	LDAPMessage *ldapEntry;
7282264Sjacobs 
7292264Sjacobs 	/* ---------- */
7302264Sjacobs 
7312264Sjacobs 	if ((ld != NULL) && (objectDN != NULL))
7322264Sjacobs 	{
7332264Sjacobs 		/* search for this Printer in the directory */
7342264Sjacobs 
7352264Sjacobs 		sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE,
7362264Sjacobs 				"(objectclass=*)", requiredAttrs, 0, &ldapMsg);
7372264Sjacobs 		if (sresult == LDAP_SUCCESS)
7382264Sjacobs 		{
7392264Sjacobs 			/* check that the object exists */
7402264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
7412264Sjacobs 			if (ldapEntry != NULL)
7422264Sjacobs 			{
7432264Sjacobs 				/* object found */
7442264Sjacobs 				result = NSL_OK;
7452264Sjacobs 			}
7462264Sjacobs 
7472264Sjacobs 			(void) ldap_msgfree(ldapMsg);
7482264Sjacobs 		}
7492264Sjacobs 	}
7502264Sjacobs 
7512264Sjacobs 	else
7522264Sjacobs 	{
7532264Sjacobs 		result = NSL_ERR_INTERNAL;
7542264Sjacobs 	}
7552264Sjacobs 
7562264Sjacobs 	return (result);
7572264Sjacobs } /* _checkPrinterDNExists */
7582264Sjacobs 
7592264Sjacobs 
7602264Sjacobs 
7612264Sjacobs 
7622264Sjacobs 
7632264Sjacobs /*
7642264Sjacobs  * *****************************************************************************
7652264Sjacobs  *
7662264Sjacobs  * Function:    _checkSunPrinter()
7672264Sjacobs  *
7682264Sjacobs  * Description: Check that the printer object for the printerDN is a sunPrinter
7692264Sjacobs  *              ie. it has the required objectclass attribute value.
7702264Sjacobs  *
7712264Sjacobs  * Parameters:
7722264Sjacobs  * Input:       LDAP *ld            - existing ldap connection descriptor
7732264Sjacobs  * Output:      uchar_t *printerDN  - DN of the printer
7742264Sjacobs  *
7752264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists and is a sunPrinter
7762264Sjacobs  *
7772264Sjacobs  * *****************************************************************************
7782264Sjacobs  */
7792264Sjacobs 
7802264Sjacobs static NSL_RESULT
_checkSunPrinter(LDAP * ld,uchar_t * printerDN)7812264Sjacobs _checkSunPrinter(LDAP *ld, uchar_t *printerDN)
7822264Sjacobs 
7832264Sjacobs {
7842264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
7852264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
7862264Sjacobs 	char *requiredAttrs[2] = { ATTR_PNAME, NULL };
7872264Sjacobs 	LDAPMessage *ldapMsg = NULL;
7882264Sjacobs 	LDAPMessage *ldapEntry = NULL;
7892264Sjacobs 	char *filter = NULL;
7902264Sjacobs 
7912264Sjacobs 	/* ---------- */
7922264Sjacobs 
7932264Sjacobs 	if ((ld != NULL) && (printerDN != NULL))
7942264Sjacobs 	{
7952264Sjacobs 		size_t size;
7962264Sjacobs 
7972264Sjacobs 		/* search for this Printer in the directory */
7982264Sjacobs 
7992264Sjacobs 		size = (3 + strlen(OCV_SUNPRT) + strlen(ATTR_OCLASS) + 2);
8002264Sjacobs 		if ((filter = malloc(size)) != NULL)
8012264Sjacobs 			(void) snprintf(filter, size, "(%s=%s)",
8022264Sjacobs 					ATTR_OCLASS, OCV_SUNPRT);
8032264Sjacobs 
8042264Sjacobs 		sresult = ldap_search_s(ld, (char *)printerDN,
8052264Sjacobs 						LDAP_SCOPE_SUBTREE, filter,
8062264Sjacobs 						requiredAttrs, 0, &ldapMsg);
8072264Sjacobs 		if (sresult == LDAP_SUCCESS)
8082264Sjacobs 		{
8092264Sjacobs 			/* check that the printer object exists */
8102264Sjacobs 
8112264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
8122264Sjacobs 			if (ldapEntry != NULL)
8132264Sjacobs 			{
8142264Sjacobs 				/* object is a sunPrinter */
8152264Sjacobs 				result = NSL_OK;
8162264Sjacobs 			}
8172264Sjacobs 
8182264Sjacobs 			(void) ldap_msgfree(ldapMsg);
8192264Sjacobs 		}
8202264Sjacobs 	}
8212264Sjacobs 
8222264Sjacobs 	else
8232264Sjacobs 	{
8242264Sjacobs 		result = NSL_ERR_INTERNAL;
8252264Sjacobs 	}
8262264Sjacobs 
8272264Sjacobs 	return (result);
8282264Sjacobs } /* _checkSunPrinter */
8292264Sjacobs 
8302264Sjacobs 
8312264Sjacobs 
8322264Sjacobs 
8332264Sjacobs 
8342264Sjacobs /*
8352264Sjacobs  * *****************************************************************************
8362264Sjacobs  *
8372264Sjacobs  * Function:    _addNewPrinterObject()
8382264Sjacobs  *
8392264Sjacobs  * Description: For the given printerName add a printer object into the
8402264Sjacobs  *              LDAP directory NS domain. The object is created with the
8412264Sjacobs  *              supplied attribute values. Note: if the printer's uri is
8422264Sjacobs  *              given that is used as the RDN otherwise the printer's
8432264Sjacobs  *              name is used as the RDN
8442264Sjacobs  *
8452264Sjacobs  * Parameters:
8462264Sjacobs  * Input:       LDAP    *ld        - existing ldap connection descriptor
8472264Sjacobs  *              uchar_t *printerName - Name of printer to be added
8482264Sjacobs  *              uchar_t *domainDN    - DN of the domain to add the printer
8492264Sjacobs  *              char    **attrList - user specified attribute values list
8502264Sjacobs  * Output:      None
8512264Sjacobs  *
8522264Sjacobs  * Returns:     NSL_RESULT - NSL_OK  = request actioned okay
8532264Sjacobs  *                           !NSL_OK = error
8542264Sjacobs  *
8552264Sjacobs  * *****************************************************************************
8562264Sjacobs  */
8572264Sjacobs 
8582264Sjacobs static NSL_RESULT
_addNewPrinterObject(LDAP * ld,uchar_t * printerName,uchar_t * domainDN,char ** attrList)8592264Sjacobs _addNewPrinterObject(LDAP *ld, uchar_t *printerName,
8602264Sjacobs 			uchar_t *domainDN, char **attrList)
8612264Sjacobs 
8622264Sjacobs {
8632264Sjacobs 	NSL_RESULT result = NSL_ERR_ADD_FAILED;
8642264Sjacobs 	int lresult = 0;
8652264Sjacobs 	uchar_t *printerDN = NULL;
8662264Sjacobs 	LDAPMod **attrs = NULL;
8672264Sjacobs 
8682264Sjacobs 	/* ---------- */
8692264Sjacobs 
8702264Sjacobs 	if ((ld != NULL) && (printerName != NULL) && (domainDN != NULL) &&
8712264Sjacobs 		(attrList != NULL) && (attrList[0] != NULL))
8722264Sjacobs 	{
8732264Sjacobs 		result = _checkAttributes(attrList);
8742264Sjacobs 
8752264Sjacobs 		if (result == NSL_OK)
8762264Sjacobs 		{
8772264Sjacobs 			/*
8782264Sjacobs 			 * construct a DN for the printer from the
8792264Sjacobs 			 * printerName and printer-uri if given.
8802264Sjacobs 			 */
8812264Sjacobs 			printerDN = _constructPrinterDN(printerName,
8822264Sjacobs 						domainDN, attrList);
8832264Sjacobs 			if (printerDN != NULL)
8842264Sjacobs 			{
8852264Sjacobs 				/*
8862264Sjacobs 				 * setup attribute values in an LDAPMod
8872264Sjacobs 				 * structure and then add the object
8882264Sjacobs 				 */
8892264Sjacobs 				result = _constructAddLDAPMod(printerName,
8902264Sjacobs 							attrList, &attrs);
8912264Sjacobs 				if (result == NSL_OK)
8922264Sjacobs 				{
8932264Sjacobs 					lresult = ldap_add_s(ld,
8942264Sjacobs 						    (char *)printerDN, attrs);
8952264Sjacobs 					if (lresult == LDAP_SUCCESS)
8962264Sjacobs 					{
8972264Sjacobs 						result = NSL_OK;
8982264Sjacobs 					}
8992264Sjacobs 					else
9002264Sjacobs 					{
9012264Sjacobs 						result = NSL_ERR_ADD_FAILED;
9022264Sjacobs #ifdef DEBUG
9032264Sjacobs (void) ldap_perror(ld, "ldap_add_s");
9042264Sjacobs #endif
9052264Sjacobs 					}
9062264Sjacobs 
9072264Sjacobs 					(void) ldap_mods_free(attrs, 1);
9082264Sjacobs 				}
9092264Sjacobs 				free(printerDN);
9102264Sjacobs 			}
9112264Sjacobs 
9122264Sjacobs 			else
9132264Sjacobs 			{
9142264Sjacobs 				result = NSL_ERR_INTERNAL;
9152264Sjacobs 			}
9162264Sjacobs 		}
9172264Sjacobs 	}
9182264Sjacobs 
9192264Sjacobs 	else
9202264Sjacobs 	{
9212264Sjacobs 		result = NSL_ERR_INTERNAL;
9222264Sjacobs 	}
9232264Sjacobs 
9242264Sjacobs 	return (result);
9252264Sjacobs } /* _addNewPrinterObject */
9262264Sjacobs 
9272264Sjacobs 
9282264Sjacobs 
9292264Sjacobs 
9302264Sjacobs 
9312264Sjacobs 
9322264Sjacobs /*
9332264Sjacobs  * *****************************************************************************
9342264Sjacobs  *
9352264Sjacobs  * Function:    _modifyPrinterObject()
9362264Sjacobs  *
9372264Sjacobs  * Description: Modify the given LDAP printer object to set the new attributes
9382264Sjacobs  *              in the attribute list. If the printer's URI (specified in the
9392264Sjacobs  *              attrList) changes the URI of the object the request is rejected.
9402264Sjacobs  *
9412264Sjacobs  * Parameters:
9422264Sjacobs  * Input:       LDAP    *ld        - existing ldap connection descriptor
9432264Sjacobs  *              uchar_t *printerDN - DN of printer object to modify
9442264Sjacobs  *              uchar_t *printerName - Name of printer to be modified
9452264Sjacobs  *              uchar_t *domainDN    - DN of the domain the printer is in
9462264Sjacobs  *              char    **attrList - user specified attribute values list
9472264Sjacobs  * Output:      None
9482264Sjacobs  *
9492264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = object modified okay
9502264Sjacobs  *
9512264Sjacobs  * *****************************************************************************
9522264Sjacobs  */
9532264Sjacobs 
9542264Sjacobs static NSL_RESULT
_modifyPrinterObject(LDAP * ld,uchar_t * printerDN,uchar_t * printerName,uchar_t * domainDN,char ** attrList)9552264Sjacobs _modifyPrinterObject(LDAP *ld, uchar_t *printerDN,
9562264Sjacobs 		uchar_t *printerName, uchar_t *domainDN, char **attrList)
9572264Sjacobs 
9582264Sjacobs {
9592264Sjacobs 	NSL_RESULT result = NSL_ERR_INTERNAL;
9602264Sjacobs 	int lresult = 0;
9612264Sjacobs 	int sunPrinter = 0;
9622264Sjacobs 	uchar_t *uriDN = NULL;
9632264Sjacobs 	LDAPMod **attrs = NULL;
9642264Sjacobs 	char **kvpList = NULL;
9652264Sjacobs 
9662264Sjacobs 	/* ---------- */
9672264Sjacobs 
9682264Sjacobs 	if ((ld != NULL) && (printerDN != NULL) && (printerName != NULL) &&
9692264Sjacobs 	    (domainDN != NULL) && (attrList != NULL) && (attrList[0] != NULL))
9702264Sjacobs 	{
9712264Sjacobs 		result = _checkAttributes(attrList);
9722264Sjacobs 
9732264Sjacobs 		if (result == NSL_OK)
9742264Sjacobs 		{
9752264Sjacobs 			/*
9762264Sjacobs 			 * The user may have requested that the printer object
9772264Sjacobs 			 * be given a new URI RDN, so construct a DN for the
9782264Sjacobs 			 * printer from the printerName or the printer-uri (if
9792264Sjacobs 			 * given).
9802264Sjacobs 			 */
9812264Sjacobs 			uriDN = _constructPrinterDN(NULL, domainDN, attrList);
9822264Sjacobs 
9832264Sjacobs 			/*
9842264Sjacobs 			 * compare the 2 DNs to see if the URI has changed,
9852264Sjacobs 			 * if uriDN is null then the DN hasn't changed
9862264Sjacobs 			 */
9872264Sjacobs 			if ((uriDN == NULL) || ((uriDN != NULL) &&
9882264Sjacobs 			    (_compareURIinDNs(printerDN, uriDN) == NSL_OK)))
9892264Sjacobs 			{
9902264Sjacobs 				/*
9912264Sjacobs 				 * setup the modify object LDAPMod
9922264Sjacobs 				 * structure and then do the modify
9932264Sjacobs 				 */
9942264Sjacobs 
9952264Sjacobs 				if (_checkSunPrinter(ld, printerDN) == NSL_OK)
9962264Sjacobs 				{
9972264Sjacobs 					sunPrinter = 1;
9982264Sjacobs 				}
9992264Sjacobs 
10002264Sjacobs 				(void) _getCurrentKVPValues(ld,
10012264Sjacobs 							printerDN, &kvpList);
10022264Sjacobs 
10032264Sjacobs 				result = _constructModLDAPMod(printerName,
10042264Sjacobs 							sunPrinter, attrList,
10052264Sjacobs 							&kvpList, &attrs);
10062264Sjacobs 				_freeList(&kvpList);
10072264Sjacobs 
10082264Sjacobs 				if ((result == NSL_OK) && (attrs != NULL))
10092264Sjacobs 				{
10102264Sjacobs 					lresult = ldap_modify_s(
10112264Sjacobs 						ld, (char *)printerDN, attrs);
10122264Sjacobs 					if (lresult == LDAP_SUCCESS)
10132264Sjacobs 					{
10142264Sjacobs 						result = NSL_OK;
10152264Sjacobs 					}
10162264Sjacobs 					else
10172264Sjacobs 					{
10182264Sjacobs 						result = NSL_ERR_MOD_FAILED;
10192264Sjacobs #ifdef DEBUG
10202264Sjacobs (void) ldap_perror(ld, "ldap_modify_s");
10212264Sjacobs #endif
10222264Sjacobs 					}
10232264Sjacobs 
10242264Sjacobs 					(void) ldap_mods_free(attrs, 1);
10252264Sjacobs 				}
10262264Sjacobs 			}
10272264Sjacobs 			else
10282264Sjacobs 			{
10292264Sjacobs 				/*
10302264Sjacobs 				 * printer-uri name change has been requested
10312264Sjacobs 				 * this is NOT allowed as it requires that
10322264Sjacobs 				 * a new printer object is created
10332264Sjacobs 				 */
10342264Sjacobs 				result = NSL_ERR_RENAME;  /* NOT ALLOWED */
10352264Sjacobs 			}
10362264Sjacobs 
10372264Sjacobs 			if (uriDN != NULL)
10382264Sjacobs 			{
10392264Sjacobs 				free(uriDN);
10402264Sjacobs 			}
10412264Sjacobs 		}
10422264Sjacobs 	}
10432264Sjacobs 
10442264Sjacobs 	return (result);
10452264Sjacobs } /* _modifyPrinterObject */
10462264Sjacobs 
10472264Sjacobs 
10482264Sjacobs 
10492264Sjacobs 
10502264Sjacobs /*
10512264Sjacobs  * *****************************************************************************
10522264Sjacobs  *
10532264Sjacobs  * Function:    _checkAttributes()
10542264Sjacobs  *
10552264Sjacobs  * Description: Check that the given attribute lists does not contain any
10562264Sjacobs  *              key words that are not allowed.
10572264Sjacobs  *
10582264Sjacobs  * Parameters:
10592264Sjacobs  * Input:       char **list - attribute list to check
10602264Sjacobs  * Output:      None
10612264Sjacobs  *
10622264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = checked okay
10632264Sjacobs  *
10642264Sjacobs  * *****************************************************************************
10652264Sjacobs  */
10662264Sjacobs 
10672264Sjacobs static NSL_RESULT
_checkAttributes(char ** list)10682264Sjacobs _checkAttributes(char **list)
10692264Sjacobs 
10702264Sjacobs {
10712264Sjacobs 	NSL_RESULT result = NSL_OK;
10722264Sjacobs 	int len = 0;
10732264Sjacobs 	char *attr = NULL;
10742264Sjacobs 	char **p = NULL;
10752264Sjacobs 
10762264Sjacobs 	/* ------ */
10772264Sjacobs 
10782264Sjacobs 	for (p = list; (p != NULL) && (*p != NULL) && (result == NSL_OK); p++)
10792264Sjacobs 	{
10802264Sjacobs 		/* get length of this key word */
10812264Sjacobs 
10822264Sjacobs 		for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
10832264Sjacobs 
10842264Sjacobs 		/* check if the key word is allowed */
10852264Sjacobs 
10862264Sjacobs 		if (strncasecmp(*p, ATTR_KVP, len) == 0)
10872264Sjacobs 		{
10882264Sjacobs 			/* not supported through this interface */
10892264Sjacobs 			result = NSL_ERR_KVP;
10902264Sjacobs 		}
10912264Sjacobs 		else
10922264Sjacobs 		if (strncasecmp(*p, ATTR_BSDADDR, len) == 0)
10932264Sjacobs 		{
10942264Sjacobs 			/* not supported through this interface */
10952264Sjacobs 			result = NSL_ERR_BSDADDR;
10962264Sjacobs 		}
10972264Sjacobs 		else
10982264Sjacobs 		if (strncasecmp(*p, ATTR_PNAME, len) == 0)
10992264Sjacobs 		{
11002264Sjacobs 			/* not supported through this interface */
11012264Sjacobs 			result = NSL_ERR_PNAME;
11022264Sjacobs 		}
11032264Sjacobs 		else
11042264Sjacobs 		{
11052264Sjacobs 			/* check for any others */
11062264Sjacobs 
11072264Sjacobs 			attr = strdup(*p);
11082264Sjacobs 			attr[len] = '\0'; /* terminate the key */
11092264Sjacobs 
11102264Sjacobs 			if (_attrInList(attr, nsl_attr_notAllowed))
11112264Sjacobs 			{
11122264Sjacobs 				result = NSL_ERR_NOTALLOWED;
11132264Sjacobs 			}
11142264Sjacobs 		}
11152264Sjacobs 
11162264Sjacobs 	}
11172264Sjacobs 
11182264Sjacobs 	return (result);
11192264Sjacobs } /* _checkAttributes */
11202264Sjacobs 
11212264Sjacobs 
11222264Sjacobs 
11232264Sjacobs 
11242264Sjacobs /*
11252264Sjacobs  * *****************************************************************************
11262264Sjacobs  *
11272264Sjacobs  * Function:    _addLDAPmodValue()
11282264Sjacobs  *
11292264Sjacobs  * Description: Add the given attribute and its value to the LDAPMod array.
11302264Sjacobs  *              If this is the first entry in the array then create it.
11312264Sjacobs  *
11322264Sjacobs  * Parameters:
11332264Sjacobs  * Input:       LDAPMod ***attrs  - array to update
11342264Sjacobs  *              char *type        - attribute to add into array
11352264Sjacobs  *              char *value       - attribute value
11362264Sjacobs  * Output:      None
11372264Sjacobs  *
11382264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = added okay
11392264Sjacobs  *
11402264Sjacobs  * *****************************************************************************
11412264Sjacobs  */
11422264Sjacobs 
11432264Sjacobs static NSL_RESULT
_addLDAPmodValue(LDAPMod *** attrs,char * type,char * value)11442264Sjacobs _addLDAPmodValue(LDAPMod ***attrs, char *type, char *value)
11452264Sjacobs 
11462264Sjacobs {
11472264Sjacobs 	int i = 0;
11482264Sjacobs 	int j = 0;
11492264Sjacobs 	NSL_RESULT result = NSL_OK;
11502264Sjacobs 
11512264Sjacobs 	/* ---------- */
11522264Sjacobs 
11532264Sjacobs 	if ((attrs != NULL) && (type != NULL) && (value != NULL))
11542264Sjacobs 	{
11552264Sjacobs #ifdef DEBUG
11562264Sjacobs printf("_addLDAPmodValue() type='%s', value='%s'\n", type, value);
11572264Sjacobs #endif
11582264Sjacobs 		/* search the existing LDAPMod array for the attribute */
11592264Sjacobs 
11602264Sjacobs 		for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++)
11612264Sjacobs 		{
11622264Sjacobs 			if (strcasecmp((*attrs)[i]->mod_type, type) == 0)
11632264Sjacobs 			{
11642264Sjacobs 				break;
11652264Sjacobs 			}
11662264Sjacobs 		}
11672264Sjacobs 
11682264Sjacobs 		if (*attrs == NULL)
11692264Sjacobs 		{
11702264Sjacobs 			/* array empty so create it */
11712264Sjacobs 
11722264Sjacobs 			*attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *));
11732264Sjacobs 			if (*attrs != NULL)
11742264Sjacobs 			{
11752264Sjacobs 				i = 0;
11762264Sjacobs 			}
11772264Sjacobs 			else
11782264Sjacobs 			{
11792264Sjacobs 				result = NSL_ERR_MEMORY;
11802264Sjacobs 			}
11812264Sjacobs 
11822264Sjacobs 		}
11832264Sjacobs 		else
11842264Sjacobs 		if ((*attrs)[i] == NULL)
11852264Sjacobs 		{
11862264Sjacobs 			*attrs = (LDAPMod **)
11872264Sjacobs 				realloc(*attrs, (i+2) * sizeof (LDAPMod *));
11882264Sjacobs 			if (*attrs == NULL)
11892264Sjacobs 			{
11902264Sjacobs 				result = NSL_ERR_MEMORY;
11912264Sjacobs 			}
11922264Sjacobs 		}
11932264Sjacobs 	}
11942264Sjacobs 	else
11952264Sjacobs 	{
11962264Sjacobs 		result = NSL_ERR_INTERNAL;
11972264Sjacobs 	}
11982264Sjacobs 
11992264Sjacobs 	if (result == NSL_OK)
12002264Sjacobs 	{
12012264Sjacobs 		if ((*attrs)[i] == NULL)
12022264Sjacobs 		{
12032264Sjacobs 			/* We've got a new slot. Create the new mod. */
12042264Sjacobs 
12052264Sjacobs 			(*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod));
12062264Sjacobs 			if ((*attrs)[i] != NULL)
12072264Sjacobs 			{
12082264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_ADD;
12092264Sjacobs 				(*attrs)[i]->mod_type = strdup(type);
12102264Sjacobs 				(*attrs)[i]->mod_values = (char **)
12112264Sjacobs 						malloc(2 * sizeof (char *));
12122264Sjacobs 				if ((*attrs)[i]->mod_values  != NULL)
12132264Sjacobs 				{
12142264Sjacobs 					(*attrs)[i]->mod_values[0] =
12152264Sjacobs 								strdup(value);
12162264Sjacobs 					(*attrs)[i]->mod_values[1] = NULL;
12172264Sjacobs 					(*attrs)[i+1] = NULL;
12182264Sjacobs 				}
12192264Sjacobs 				else
12202264Sjacobs 				{
12212264Sjacobs 					result = NSL_ERR_MEMORY;
12222264Sjacobs 				}
12232264Sjacobs 			}
12242264Sjacobs 			else
12252264Sjacobs 			{
12262264Sjacobs 				result = NSL_ERR_MEMORY;
12272264Sjacobs 			}
12282264Sjacobs 		}
12292264Sjacobs 
12302264Sjacobs 		else
12312264Sjacobs 		{
12322264Sjacobs 			/* Found an existing entry so add value to it */
12332264Sjacobs 
12342264Sjacobs 			for (j = 0; (*attrs)[i]->mod_values[j] != NULL; j++);
12352264Sjacobs 
12362264Sjacobs 			(*attrs)[i]->mod_values =
12372264Sjacobs 				(char **)realloc((*attrs)[i]->mod_values,
12382264Sjacobs 						(j + 2) * sizeof (char *));
12392264Sjacobs 			if ((*attrs)[i]->mod_values != NULL)
12402264Sjacobs 			{
12412264Sjacobs 				(*attrs)[i]->mod_values[j] = strdup(value);
12422264Sjacobs 				(*attrs)[i]->mod_values[j+1] = NULL;
12432264Sjacobs 			}
12442264Sjacobs 			else
12452264Sjacobs 			{
12462264Sjacobs 				result = NSL_ERR_MEMORY;
12472264Sjacobs 			}
12482264Sjacobs 		}
12492264Sjacobs 	}
12502264Sjacobs 
12512264Sjacobs 	return (result);
12522264Sjacobs } /* _addLDAPmodValue */
12532264Sjacobs 
12542264Sjacobs 
12552264Sjacobs 
12562264Sjacobs 
12572264Sjacobs /*
12582264Sjacobs  * *****************************************************************************
12592264Sjacobs  *
12602264Sjacobs  * Function:    _modLDAPmodValue()
12612264Sjacobs  *
12622264Sjacobs  * Description: Add the given attribute modify operation and its value into
12632264Sjacobs  *              the LDAPMod array. This will either be a "replace" or a
12642264Sjacobs  *              "delete"; value = null implies a "delete".
12652264Sjacobs  *              If this is the first entry in the array then create it.
12662264Sjacobs  *
12672264Sjacobs  * Parameters:
12682264Sjacobs  * Input:       LDAPMod ***attrs  - array to update
12692264Sjacobs  *              char *type        - attribute to modify
12702264Sjacobs  *              char *value       - attribute value, null implies "delete"
12712264Sjacobs  * Output:      None
12722264Sjacobs  *
12732264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = added okay
12742264Sjacobs  *
12752264Sjacobs  * *****************************************************************************
12762264Sjacobs  */
12772264Sjacobs 
12782264Sjacobs static NSL_RESULT
_modLDAPmodValue(LDAPMod *** attrs,char * type,char * value)12792264Sjacobs _modLDAPmodValue(LDAPMod ***attrs, char *type, char *value)
12802264Sjacobs 
12812264Sjacobs {
12822264Sjacobs 	int i = 0;
12832264Sjacobs 	int j = 0;
12842264Sjacobs 	NSL_RESULT result = NSL_OK;
12852264Sjacobs 
12862264Sjacobs 	/* ---------- */
12872264Sjacobs 
12882264Sjacobs 	if ((attrs != NULL) && (type != NULL))
12892264Sjacobs 	{
12902264Sjacobs #ifdef DEBUG
12912264Sjacobs if (value != NULL)
12922264Sjacobs printf("_modLDAPmodValue() REPLACE type='%s', value='%s'\n", type, value);
12932264Sjacobs else
12942264Sjacobs printf("_modLDAPmodValue() DELETE type='%s'\n", type);
12952264Sjacobs #endif
12962264Sjacobs 		/* search the existing LDAPMod array for the attribute */
12972264Sjacobs 
12982264Sjacobs 		for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++)
12992264Sjacobs 		{
13002264Sjacobs 			if (strcasecmp((*attrs)[i]->mod_type, type) == 0)
13012264Sjacobs 			{
13022264Sjacobs 				break;
13032264Sjacobs 			}
13042264Sjacobs 		}
13052264Sjacobs 
13062264Sjacobs 		if (*attrs == NULL)
13072264Sjacobs 		{
13082264Sjacobs 			/* array empty so create it */
13092264Sjacobs 
13102264Sjacobs 			*attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *));
13112264Sjacobs 			if (*attrs != NULL)
13122264Sjacobs 			{
13132264Sjacobs 				i = 0;
13142264Sjacobs 			}
13152264Sjacobs 			else
13162264Sjacobs 			{
13172264Sjacobs 				result = NSL_ERR_MEMORY;
13182264Sjacobs 			}
13192264Sjacobs 
13202264Sjacobs 		}
13212264Sjacobs 		else
13222264Sjacobs 		if ((*attrs)[i] == NULL)
13232264Sjacobs 		{
13242264Sjacobs 			/* attribute not found in array so add slot for it */
13252264Sjacobs 
13262264Sjacobs 			*attrs = (LDAPMod **)
13272264Sjacobs 				realloc(*attrs, (i+2) * sizeof (LDAPMod *));
13282264Sjacobs 			if (*attrs == NULL)
13292264Sjacobs 			{
13302264Sjacobs 				result = NSL_ERR_MEMORY;
13312264Sjacobs 			}
13322264Sjacobs 		}
13332264Sjacobs 	}
13342264Sjacobs 	else
13352264Sjacobs 	{
13362264Sjacobs 		result = NSL_ERR_INTERNAL;
13372264Sjacobs 	}
13382264Sjacobs 
13392264Sjacobs 	if (result == NSL_OK)
13402264Sjacobs 	{
13412264Sjacobs 		if ((*attrs)[i] == NULL)
13422264Sjacobs 		{
13432264Sjacobs 			/* We've got a new slot. Create the new mod entry */
13442264Sjacobs 
13452264Sjacobs 			(*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod));
13462264Sjacobs 			if (((*attrs)[i] != NULL) && (value != NULL))
13472264Sjacobs 			{
13482264Sjacobs 				/* Do an attribute replace */
13492264Sjacobs 
13502264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_REPLACE;
13512264Sjacobs 				(*attrs)[i]->mod_type = strdup(type);
13522264Sjacobs 				(*attrs)[i]->mod_values = (char **)
13532264Sjacobs 						malloc(2 * sizeof (char *));
13542264Sjacobs 				if ((*attrs)[i]->mod_values  != NULL)
13552264Sjacobs 				{
13562264Sjacobs 					(*attrs)[i]->mod_values[0] =
13572264Sjacobs 								strdup(value);
13582264Sjacobs 					(*attrs)[i]->mod_values[1] = NULL;
13592264Sjacobs 					(*attrs)[i+1] = NULL;
13602264Sjacobs 				}
13612264Sjacobs 				else
13622264Sjacobs 				{
13632264Sjacobs 					result = NSL_ERR_MEMORY;
13642264Sjacobs 				}
13652264Sjacobs 			}
13662264Sjacobs 			else
13672264Sjacobs 			if ((*attrs)[i] != NULL)
13682264Sjacobs 			{
13692264Sjacobs 				/* value is null so do an attribute delete */
13702264Sjacobs 
13712264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_DELETE;
13722264Sjacobs 				(*attrs)[i]->mod_type = strdup(type);
13732264Sjacobs 				(*attrs)[i]->mod_values = NULL;
13742264Sjacobs 				(*attrs)[i+1] = NULL;
13752264Sjacobs 			}
13762264Sjacobs 			else
13772264Sjacobs 			{
13782264Sjacobs 				result = NSL_ERR_MEMORY; /* malloc failed */
13792264Sjacobs 			}
13802264Sjacobs 		}
13812264Sjacobs 
13822264Sjacobs 		else
13832264Sjacobs 		{
13842264Sjacobs 			/* Found an existing entry so add value to it */
13852264Sjacobs 
13862264Sjacobs 			if (value != NULL)
13872264Sjacobs 			{
13882264Sjacobs 			    /* add value to attribute's replace list */
13892264Sjacobs 
13902264Sjacobs 			    if ((*attrs)[i]->mod_op == LDAP_MOD_REPLACE)
13912264Sjacobs 			    {
13922264Sjacobs 				for (j = 0;
13932264Sjacobs 				    (*attrs)[i]->mod_values[j] != NULL; j++);
13942264Sjacobs 
13952264Sjacobs 				(*attrs)[i]->mod_values =
13962264Sjacobs 				(char **)realloc((*attrs)[i]->mod_values,
13972264Sjacobs 						(j + 2) * sizeof (char *));
13982264Sjacobs 				if ((*attrs)[i]->mod_values != NULL)
13992264Sjacobs 				{
14002264Sjacobs 					(*attrs)[i]->mod_values[j] =
14012264Sjacobs 								strdup(value);
14022264Sjacobs 					(*attrs)[i]->mod_values[j+1] = NULL;
14032264Sjacobs 				}
14042264Sjacobs 				else
14052264Sjacobs 				{
14062264Sjacobs 					result = NSL_ERR_MEMORY;
14072264Sjacobs 				}
14082264Sjacobs 			    }
14092264Sjacobs 			    else
14102264Sjacobs 			    {
14112264Sjacobs 				/* Delete and replace not allowed */
14122264Sjacobs 				result = NSL_ERR_MULTIOP;
14132264Sjacobs 			    }
14142264Sjacobs 			}
14152264Sjacobs 
14162264Sjacobs 			else
14172264Sjacobs 			{
14182264Sjacobs 				/*
14192264Sjacobs 				 * attribute delete - so free any existing
14202264Sjacobs 				 * entries in the value array
14212264Sjacobs 				 */
14222264Sjacobs 
14232264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_DELETE;
14242264Sjacobs 
14252264Sjacobs 				if ((*attrs)[i]->mod_values != NULL)
14262264Sjacobs 				{
14272264Sjacobs 					for (j = 0;
14282264Sjacobs 					    (*attrs)[i]->mod_values[j] != NULL;
14292264Sjacobs 					    j++)
14302264Sjacobs 					{
14312264Sjacobs 					    free((*attrs)[i]->mod_values[j]);
14322264Sjacobs 					}
14332264Sjacobs 
14342264Sjacobs 					free((*attrs)[i]->mod_values);
14352264Sjacobs 					(*attrs)[i]->mod_values = NULL;
14362264Sjacobs 				}
14372264Sjacobs 			}
14382264Sjacobs 		}
14392264Sjacobs 	}
14402264Sjacobs 
14412264Sjacobs 	return (result);
14422264Sjacobs } /* _modLDAPmodValue */
14432264Sjacobs 
14442264Sjacobs 
14452264Sjacobs 
14462264Sjacobs 
14472264Sjacobs 
14482264Sjacobs /*
14492264Sjacobs  * *****************************************************************************
14502264Sjacobs  *
14512264Sjacobs  * Function:    _constructAddLDAPMod()
14522264Sjacobs  *
14532264Sjacobs  * Description: For the given attribute list construct an
14542264Sjacobs  *              LDAPMod array for the printer object to be added. Default
14552264Sjacobs  *              attribute values are included.
14562264Sjacobs  *
14572264Sjacobs  * Parameters:
14582264Sjacobs  * Input:
14592264Sjacobs  *              uchar_t *printerName - Name of printer to be added
14602264Sjacobs  *              char    **attrList - user specified attribute values list
14612264Sjacobs  * Output:      LDAPMod ***attrs  - pointer to the constructed array
14622264Sjacobs  *
14632264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = constructed okay
14642264Sjacobs  *
14652264Sjacobs  * *****************************************************************************
14662264Sjacobs  */
14672264Sjacobs 
14682264Sjacobs static NSL_RESULT
_constructAddLDAPMod(uchar_t * printerName,char ** attrList,LDAPMod *** attrs)14692264Sjacobs _constructAddLDAPMod(uchar_t *printerName, char **attrList,  LDAPMod ***attrs)
14702264Sjacobs 
14712264Sjacobs {
14722264Sjacobs 	NSL_RESULT result = NSL_ERROR;
14732264Sjacobs 	int len = 0;
14742264Sjacobs 	char **p = NULL;
14752264Sjacobs 	char *value = NULL;
14762264Sjacobs 	char *attr = NULL;
14772264Sjacobs 
14782264Sjacobs 	/* ---------- */
14792264Sjacobs 
14802264Sjacobs 	if ((printerName != NULL) &&
14812264Sjacobs 	    ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL))
14822264Sjacobs 	{
14832264Sjacobs 		*attrs = NULL;
14842264Sjacobs 
14852264Sjacobs 		/*
14862264Sjacobs 		 * setup printer object attribute values in an LDAPMod structure
14872264Sjacobs 		 */
14882264Sjacobs 		result = _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_TOP);
14892264Sjacobs 		if (result == NSL_OK)
14902264Sjacobs 		{
14912264Sjacobs 			/* Structural Objectclass */
14922264Sjacobs 			result =
14932264Sjacobs 			    _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_PSERVICE);
14942264Sjacobs 		}
14952264Sjacobs 		if (result == NSL_OK)
14962264Sjacobs 		{
14972264Sjacobs 			result = _addLDAPmodValue(attrs,
14982264Sjacobs 						ATTR_OCLASS, OCV_PABSTRACT);
14992264Sjacobs 		}
15002264Sjacobs 		if (result == NSL_OK)
15012264Sjacobs 		{
15022264Sjacobs 			result = _addLDAPmodValue(attrs,
15032264Sjacobs 						ATTR_OCLASS, OCV_SUNPRT);
15042264Sjacobs 		}
15052264Sjacobs 		if (result == NSL_OK)
15062264Sjacobs 		{
15072264Sjacobs 			result = _addLDAPmodValue(attrs,
15082264Sjacobs 					ATTR_PNAME, (char *)printerName);
15092264Sjacobs 		}
15102264Sjacobs 
15112264Sjacobs 		/*
15122264Sjacobs 		 * Now work through the user supplied attribute
15132264Sjacobs 		 * values list and add them into the LDAPMod array
15142264Sjacobs 		 */
15152264Sjacobs 
15162264Sjacobs 		for (p = attrList;
15172264Sjacobs 			(p != NULL) && (*p != NULL) && (result == NSL_OK); p++)
15182264Sjacobs 		{
15192264Sjacobs 			/* get length of this key word */
15202264Sjacobs 
15212264Sjacobs 			for (len = 0;
15222264Sjacobs 			    ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
15232264Sjacobs 
15242264Sjacobs 			if ((strlen(*p) > len+1))
15252264Sjacobs 			{
15262264Sjacobs 				attr = strdup(*p);
15272264Sjacobs 				attr[len] = '\0';
15282264Sjacobs 				value = strdup(&attr[len+1]);
15292264Sjacobs 
15302264Sjacobs 				/* handle specific Key Value Pairs (KVP) */
15312264Sjacobs 
15322264Sjacobs 				if (strcasecmp(attr, NS_KEY_BSDADDR) == 0)
15332264Sjacobs 				{
15342264Sjacobs 					/* use LDAP attribute name */
15352264Sjacobs 					free(attr);
15362264Sjacobs 					attr = strdup(ATTR_BSDADDR);
15372264Sjacobs 				}
15382264Sjacobs 				else
15392264Sjacobs 				if (_attrInLDAPList(attr) == 0)
15402264Sjacobs 				{
15412264Sjacobs 					/*
15422264Sjacobs 					 * Non-LDAP attribute so use LDAP
15432264Sjacobs 					 * KVP attribute and the given KVP
15442264Sjacobs 					 * as the value, ie.
15452264Sjacobs 					 * sun-printer-kvp=description=printer
15462264Sjacobs 					 */
15472264Sjacobs 					free(attr);
15482264Sjacobs 					attr = strdup(ATTR_KVP);
15492264Sjacobs 					value = strdup(*p);
15502264Sjacobs 				}
15512264Sjacobs 
15522264Sjacobs 				/* add it into the LDAPMod array */
15532264Sjacobs 
15542264Sjacobs 				result = _addLDAPmodValue(attrs, attr, value);
15552264Sjacobs 
15562264Sjacobs 				free(attr);
15572264Sjacobs 				free(value);
15582264Sjacobs 			}
15592264Sjacobs 		} /* for */
15602264Sjacobs 
15612264Sjacobs 		if ((result != NSL_OK) && (*attrs != NULL))
15622264Sjacobs 		{
15632264Sjacobs 			(void) ldap_mods_free(*attrs, 1);
15642264Sjacobs 			attrs = NULL;
15652264Sjacobs 		}
15662264Sjacobs 	}
15672264Sjacobs 	else
15682264Sjacobs 	{
15692264Sjacobs 		result = NSL_ERR_INTERNAL;
15702264Sjacobs 	}
15712264Sjacobs 
15722264Sjacobs 	return (result);
15732264Sjacobs } /* _constructAddLDAPMod */
15742264Sjacobs 
15752264Sjacobs 
15762264Sjacobs 
15772264Sjacobs 
15782264Sjacobs 
15792264Sjacobs 
15802264Sjacobs 
15812264Sjacobs /*
15822264Sjacobs  * *****************************************************************************
15832264Sjacobs  *
15842264Sjacobs  * Function:    _constructModLDAPMod()
15852264Sjacobs  *
15862264Sjacobs  * Description: For the given modify attribute list, construct an
15872264Sjacobs  *              LDAPMod array for the printer object to be modified
15882264Sjacobs  *
15892264Sjacobs  * Parameters:
15902264Sjacobs  * Input:       uchar_t *printerName - name of printer to be modified
15912264Sjacobs  *              int     sunPrinter - Boolean; object is a sunPrinter
15922264Sjacobs  *              char    **attrList - user specified attribute values list
15932264Sjacobs  *              char    ***oldKVPList - current list of KVP values on object
15942264Sjacobs  * Output:      LDAPMod ***attrs  - pointer to the constructed array
15952264Sjacobs  *
15962264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = constructed okay
15972264Sjacobs  *
15982264Sjacobs  * *****************************************************************************
15992264Sjacobs  */
16002264Sjacobs 
16012264Sjacobs static NSL_RESULT
_constructModLDAPMod(uchar_t * printerName,int sunPrinter,char ** attrList,char *** oldKVPList,LDAPMod *** attrs)16022264Sjacobs _constructModLDAPMod(uchar_t *printerName, int sunPrinter, char **attrList,
16032264Sjacobs 			char ***oldKVPList, LDAPMod ***attrs)
16042264Sjacobs 
16052264Sjacobs {
16062264Sjacobs 	NSL_RESULT result = NSL_OK;
16072264Sjacobs 	int len = 0;
16082264Sjacobs 	int kvpUpdated = 0;
16092264Sjacobs 	int kvpExists = 0;
16102264Sjacobs 	char **p = NULL;
16112264Sjacobs 	char *value = NULL;
16122264Sjacobs 	char *attr = NULL;
16132264Sjacobs 
16142264Sjacobs 	/* ---------- */
16152264Sjacobs 
16162264Sjacobs 	if ((printerName != NULL) &&
16172264Sjacobs 	    ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL))
16182264Sjacobs 	{
16192264Sjacobs 		*attrs = NULL;
16202264Sjacobs 
16212264Sjacobs 		if ((oldKVPList != NULL) && (*oldKVPList != NULL))
16222264Sjacobs 		{
16232264Sjacobs 			kvpExists = 1;
16242264Sjacobs 		}
16252264Sjacobs 
16262264Sjacobs 		if (!sunPrinter)
16272264Sjacobs 		{
16282264Sjacobs 			/*
16292264Sjacobs 			 * The object was previously not a sunPrinter, so
16302264Sjacobs 			 * add the required objectclass attribute value, and
16312264Sjacobs 			 * ensure it has the printername attribute.
16322264Sjacobs 			 */
16332264Sjacobs 			result = _addLDAPmodValue(attrs,
16342264Sjacobs 						ATTR_OCLASS, OCV_SUNPRT);
16352264Sjacobs 			if (result == NSL_OK)
16362264Sjacobs 			{
16372264Sjacobs 				result = _modLDAPmodValue(attrs,
16382264Sjacobs 					    ATTR_PNAME, (char *)printerName);
16392264Sjacobs 			}
16402264Sjacobs 		}
16412264Sjacobs 
16422264Sjacobs 		/*
16432264Sjacobs 		 * work through the user supplied attribute
16442264Sjacobs 		 * values list and add them into the LDAPMod array depending
16452264Sjacobs 		 * on if they are a replace or delete attribute operation,
16462264Sjacobs 		 * a "null value" means delete.
16472264Sjacobs 		 */
16482264Sjacobs 
16492264Sjacobs 		for (p = attrList;
16502264Sjacobs 			(p != NULL) && (*p != NULL) && (result == NSL_OK); p++)
16512264Sjacobs 		{
16522264Sjacobs 			/* get length of this key word */
16532264Sjacobs 
16542264Sjacobs 			for (len = 0;
16552264Sjacobs 			    ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
16562264Sjacobs 
16572264Sjacobs 			if ((strlen(*p) > len+1))
16582264Sjacobs 			{
16592264Sjacobs 				attr = strdup(*p);
16602264Sjacobs 				attr[len] = '\0';
16612264Sjacobs 				value = strdup(&attr[len+1]);
16622264Sjacobs 
16632264Sjacobs 				/* handle specific Key Value Pairs (KVP) */
16642264Sjacobs 
16652264Sjacobs 				if ((_attrInLDAPList(attr) == 0) &&
16662264Sjacobs 					(strcasecmp(attr, NS_KEY_BSDADDR) != 0))
16672264Sjacobs 				{
16682264Sjacobs 					/*
16692264Sjacobs 					 * Non-LDAP attribute so use LDAP
16702264Sjacobs 					 * KVP attribute and the given KVP as
16712264Sjacobs 					 * the value, ie.
16722264Sjacobs 					 * sun-printer-kvp=description=printer
16732264Sjacobs 					 */
16742264Sjacobs 					result = _modAttrKVP(*p, oldKVPList);
16752264Sjacobs 					kvpUpdated = 1;
16762264Sjacobs 				}
16772264Sjacobs 
16782264Sjacobs 				else
16792264Sjacobs 				{
16802264Sjacobs 					if (strcasecmp(attr, NS_KEY_BSDADDR) ==
16812264Sjacobs 									0)
16822264Sjacobs 					{
16832264Sjacobs 						/*
16842264Sjacobs 						 * use LDAP bsdaddr attribute
16852264Sjacobs 						 * name
16862264Sjacobs 						 */
16872264Sjacobs 						free(attr);
16882264Sjacobs 						attr = strdup(ATTR_BSDADDR);
16892264Sjacobs 					}
16902264Sjacobs 
16912264Sjacobs 					/*
16922264Sjacobs 					 * else
16932264Sjacobs 					 *   use the supplied attribute name
16942264Sjacobs 					 */
16952264Sjacobs 
16962264Sjacobs 					/* add it into the LDAPMod array */
16972264Sjacobs 
16982264Sjacobs 					result = _modLDAPmodValue(attrs,
16992264Sjacobs 								attr, value);
17002264Sjacobs 				}
17012264Sjacobs 
17022264Sjacobs 				free(attr);
17032264Sjacobs 				free(value);
17042264Sjacobs 			}
17052264Sjacobs 
17062264Sjacobs 			else
17072264Sjacobs 			if (strlen(*p) >= 1)
17082264Sjacobs 			{
17092264Sjacobs 				/* handle attribute DELETE request */
17102264Sjacobs 
17112264Sjacobs 				attr = strdup(*p);
17122264Sjacobs 				if (attr[len] == '=')
17132264Sjacobs 				{
17142264Sjacobs 					/* terminate "attribute=" */
17152264Sjacobs 					attr[len] = '\0';
17162264Sjacobs 				}
17172264Sjacobs 
17182264Sjacobs 				/* handle specific Key Value Pairs (KVP) */
17192264Sjacobs 
17202264Sjacobs 				if (strcasecmp(attr, NS_KEY_BSDADDR) == 0)
17212264Sjacobs 				{
17222264Sjacobs 					/* use LDAP bsdaddr attribute name */
17232264Sjacobs 					result = _modLDAPmodValue(attrs,
17242264Sjacobs 							ATTR_BSDADDR, NULL);
17252264Sjacobs 				}
17262264Sjacobs 				else
17272264Sjacobs 				if (_attrInLDAPList(attr) == 0)
17282264Sjacobs 				{
17292264Sjacobs 					/*
17302264Sjacobs 					 * Non-LDAP kvp, so sort items
17312264Sjacobs 					 * in the kvp list
17322264Sjacobs 					 */
17332264Sjacobs 					result = _modAttrKVP(*p, oldKVPList);
17342264Sjacobs 					kvpUpdated = 1;
17352264Sjacobs 				}
17362264Sjacobs 				else
17372264Sjacobs 				{
17382264Sjacobs 					result = _modLDAPmodValue(attrs,
17392264Sjacobs 							attr, NULL);
17402264Sjacobs 				}
17412264Sjacobs 
17422264Sjacobs 				free(attr);
17432264Sjacobs 			}
17442264Sjacobs 		} /* for */
17452264Sjacobs 
17462264Sjacobs 		if ((result == NSL_OK) && (kvpUpdated))
17472264Sjacobs 		{
17482264Sjacobs 			result = _attrAddKVP(attrs, *oldKVPList, kvpExists);
17492264Sjacobs 		}
17502264Sjacobs 
17512264Sjacobs 		if ((result != NSL_OK) && (*attrs != NULL))
17522264Sjacobs 		{
17532264Sjacobs 			(void) ldap_mods_free(*attrs, 1);
17542264Sjacobs 			*attrs = NULL;
17552264Sjacobs 		}
17562264Sjacobs 	}
17572264Sjacobs 	else
17582264Sjacobs 	{
17592264Sjacobs 		result = NSL_ERR_INTERNAL;
17602264Sjacobs 	}
17612264Sjacobs 
17622264Sjacobs 	return (result);
17632264Sjacobs } /* _constructModLDAPMod */
17642264Sjacobs 
17652264Sjacobs 
17662264Sjacobs 
17672264Sjacobs 
17682264Sjacobs 
17692264Sjacobs 
17702264Sjacobs /*
17712264Sjacobs  * *****************************************************************************
17722264Sjacobs  *
17732264Sjacobs  * Function:    _compareURIinDNs()
17742264Sjacobs  *
17752264Sjacobs  * Description: For the 2 given printer object DNs compare the naming part
17762264Sjacobs  *              part of the DN (printer-uri) to see if they are the same.
17772264Sjacobs  *
17782264Sjacobs  * Note:        This function only returns "compare failed" if their URI don't
17792264Sjacobs  *              compare. Problems with the dn etc., return a good compare
17802264Sjacobs  *              because I don't want us to create a new object for these
17812264Sjacobs  *
17822264Sjacobs  * Parameters:
17832264Sjacobs  * Input:       uchar_t *dn1
17842264Sjacobs  *              uchar_t *dn2
17852264Sjacobs  * Output:      None
17862264Sjacobs  *
17872264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = URIs are the same
17882264Sjacobs  *
17892264Sjacobs  * *****************************************************************************
17902264Sjacobs  */
17912264Sjacobs 
17922264Sjacobs static NSL_RESULT
_compareURIinDNs(uchar_t * dn1,uchar_t * dn2)17932264Sjacobs _compareURIinDNs(uchar_t *dn1, uchar_t *dn2)
17942264Sjacobs 
17952264Sjacobs {
17962264Sjacobs 	NSL_RESULT result = NSL_OK;
17972264Sjacobs 	uchar_t *DN1 = NULL;
17982264Sjacobs 	uchar_t *DN2 = NULL;
17992264Sjacobs 	char *p1 = NULL;
18002264Sjacobs 	char *p2 = NULL;
18012264Sjacobs 
18022264Sjacobs 	/* --------- */
18032264Sjacobs 
18042264Sjacobs 	if ((dn1 != NULL) && (dn2 != NULL))
18052264Sjacobs 	{
18062264Sjacobs 		DN1 = (uchar_t *)strdup((char *)dn1);
18072264Sjacobs 		DN2 = (uchar_t *)strdup((char *)dn2);
18082264Sjacobs 
18092264Sjacobs 		/* terminate each string after the printer-uri */
18102264Sjacobs 
18112264Sjacobs 		p1 = strstr((char *)DN1, PCONTAINER);
18122264Sjacobs 		/* move back to the comma */
18132264Sjacobs 		while ((p1 != NULL) && (*p1 != ',') && (p1 >= (char *)DN1))
18142264Sjacobs 		{
18152264Sjacobs 			p1--;
18162264Sjacobs 		}
18172264Sjacobs 
18182264Sjacobs 		p2 = strstr((char *)DN2, PCONTAINER);
18192264Sjacobs 		/* move back to the comma */
18202264Sjacobs 		while ((p2 != NULL) && (*p2 != ',') && (p2 >= (char *)DN2))
18212264Sjacobs 		{
18222264Sjacobs 			p2--;
18232264Sjacobs 		}
18242264Sjacobs 
18252264Sjacobs 		if ((*p1 == ',') && (*p2 == ','))
18262264Sjacobs 		{
18272264Sjacobs 			*p1 = '\0';	/* re-terminate it */
18282264Sjacobs 			*p2 = '\0';	/* re-terminate it */
18292264Sjacobs 
18302264Sjacobs 			/* do the compare */
18312264Sjacobs 
18322264Sjacobs 			/*
18332264Sjacobs 			 * Note: SHOULD really normalise the 2 DNs before
18342264Sjacobs 			 * doing the compare
18352264Sjacobs 			 */
18362264Sjacobs #ifdef DEBUG
18372264Sjacobs printf("_compareURIinDNs() @1 (%s) (%s)\n", DN1, DN2);
18382264Sjacobs #endif
18392264Sjacobs 			if (strcasecmp((char *)DN1, (char *)DN2) != 0)
18402264Sjacobs 			{
18412264Sjacobs 				result = NSL_ERROR;
18422264Sjacobs 			}
18432264Sjacobs 
18442264Sjacobs 		}
18452264Sjacobs 
18462264Sjacobs 		free(DN1);
18472264Sjacobs 		free(DN2);
18482264Sjacobs 	}
18492264Sjacobs 
18502264Sjacobs 	return (result);
18512264Sjacobs } /* _compareURIinDNs */
18522264Sjacobs 
18532264Sjacobs 
18542264Sjacobs 
18552264Sjacobs 
18562264Sjacobs 
18572264Sjacobs 
18582264Sjacobs 
18592264Sjacobs /*
18602264Sjacobs  * *****************************************************************************
18612264Sjacobs  *
18622264Sjacobs  * Function:    _getThisNSDomainDN()
18632264Sjacobs  *
18642264Sjacobs  * Description: Get the current Name Service Domain DN
18652264Sjacobs  *              This is extracted from the result of executing ldaplist.
18662264Sjacobs  *
18672264Sjacobs  * Note:        Do it this way until the NS LDAP library interface is
18682264Sjacobs  *              made public.
18692264Sjacobs  *
18702264Sjacobs  * Parameters:
18712264Sjacobs  * Input:       None
18722264Sjacobs  * Output:      None
18732264Sjacobs  *
18742264Sjacobs  * Returns:     uchar_t*  - pointer to NS Domain DN (The caller should free this
18752264Sjacobs  *                          returned memory).
18762264Sjacobs  *
18772264Sjacobs  * *****************************************************************************
18782264Sjacobs  */
18792264Sjacobs 
18802264Sjacobs #define	LDAPLIST_D	"/usr/bin/ldaplist -d 2>&1"
18812264Sjacobs #define	DNID		"dn: "
18822264Sjacobs 
18832264Sjacobs static uchar_t *
_getThisNSDomainDN(void)18842264Sjacobs _getThisNSDomainDN(void)
18852264Sjacobs 
18862264Sjacobs {
18872264Sjacobs 	uchar_t *domainDN = NULL;
18882264Sjacobs 	char *cp = NULL;
18892264Sjacobs 	char buf[BUFSIZ] = "";
18902264Sjacobs 
18912264Sjacobs 	/* --------- */
18922264Sjacobs 
18932264Sjacobs 	if (_popen(LDAPLIST_D, buf, sizeof (buf)) == 0)
18942264Sjacobs 	{
18952264Sjacobs 		if ((cp = strstr(buf, DNID)) != NULL)
18962264Sjacobs 		{
18972264Sjacobs 			cp += strlen(DNID);  /* increment past "dn: " label */
18982264Sjacobs 			domainDN = (uchar_t *)strdup(cp);
18992264Sjacobs 
19002264Sjacobs 			if ((cp = strchr((char *)domainDN, '\n')) != NULL)
19012264Sjacobs 			{
19022264Sjacobs 				*cp = '\0'; /* terminate it */
19032264Sjacobs 			}
19042264Sjacobs 		}
19052264Sjacobs 	}
19062264Sjacobs 
19072264Sjacobs 	return (domainDN);
19082264Sjacobs } /* _getThisNSDomainDN */
19092264Sjacobs 
19102264Sjacobs 
19112264Sjacobs 
19122264Sjacobs 
19132264Sjacobs 
19142264Sjacobs /*
19152264Sjacobs  * *****************************************************************************
19162264Sjacobs  *
19172264Sjacobs  * Function:    _popen()
19182264Sjacobs  *
19192264Sjacobs  * Description: General popen function. The caller should always use a full
19202264Sjacobs  *              path cmd.
19212264Sjacobs  *
19222264Sjacobs  * Parameters:
19232264Sjacobs  * Input:       char *cmd - command line to execute
19242264Sjacobs  *              char *buffer - ptr to buffer to put result in
19252264Sjacobs  *              int  size - size of result buffer
19262264Sjacobs  * Output:      None
19272264Sjacobs  *
19282264Sjacobs  * Returns:     int - 0 = opened okay
19292264Sjacobs  *
19302264Sjacobs  * *****************************************************************************
19312264Sjacobs  */
19322264Sjacobs 
19332264Sjacobs static int
_popen(char * cmd,char * buffer,int size)19342264Sjacobs _popen(char *cmd, char *buffer, int size)
19352264Sjacobs 
19362264Sjacobs {
19372264Sjacobs 	int result = -1;
19382264Sjacobs 	int rsize = 0;
19392264Sjacobs 	FILE *fptr;
19402264Sjacobs 	char safe_cmd[BUFSIZ];
19412264Sjacobs 	char linebuf[BUFSIZ];
19422264Sjacobs 
19432264Sjacobs 	/* -------- */
19442264Sjacobs 
19452264Sjacobs 	if ((cmd != NULL) && (buffer != NULL) && (size != 0))
19462264Sjacobs 	{
19472264Sjacobs 		(void) strcpy(buffer, "");
19482264Sjacobs 		(void) strcpy(linebuf, "");
19492264Sjacobs 		(void) snprintf(safe_cmd, BUFSIZ, "IFS=' \t'; %s", cmd);
19502264Sjacobs 
19512264Sjacobs 		if ((fptr = popen(safe_cmd, "r")) != NULL)
19522264Sjacobs 		{
19532264Sjacobs 			while ((fgets(linebuf, BUFSIZ, fptr) != NULL) &&
19542264Sjacobs 							(rsize  < size))
19552264Sjacobs 			{
19562264Sjacobs 				rsize = strlcat(buffer, linebuf, size);
19572264Sjacobs 				if (rsize >= size)
19582264Sjacobs 				{
19592264Sjacobs 					/* result is too long */
19602264Sjacobs 					(void) memset(buffer, '\0', size);
19612264Sjacobs 				}
19622264Sjacobs 			}
19632264Sjacobs 
19642264Sjacobs 			if (strlen(buffer) > 0)
19652264Sjacobs 			{
19662264Sjacobs 				result = 0;
19672264Sjacobs 			}
19682264Sjacobs 
19692264Sjacobs 			(void) pclose(fptr);
19702264Sjacobs 		}
19712264Sjacobs 	}
19722264Sjacobs 
19732264Sjacobs 	return (result);
19742264Sjacobs } /* popen */
19752264Sjacobs 
19762264Sjacobs 
19772264Sjacobs /*
19782264Sjacobs  * *****************************************************************************
19792264Sjacobs  *
19802264Sjacobs  * Function:    _attrInList()
19812264Sjacobs  *
19822264Sjacobs  * Description: For the given list check if the attribute is it
19832264Sjacobs  *
19842264Sjacobs  * Parameters:
19852264Sjacobs  * Input:       char *attr   - attribute to check
19862264Sjacobs  *              char **list  - list of attributes to check against
19872264Sjacobs  * Output:      None
19882264Sjacobs  *
19892264Sjacobs  * Returns:     int - TRUE = attr found in list
19902264Sjacobs  *
19912264Sjacobs  * *****************************************************************************
19922264Sjacobs  */
19932264Sjacobs 
19942264Sjacobs static int
_attrInList(char * attr,const char ** list)19952264Sjacobs _attrInList(char *attr, const char **list)
19962264Sjacobs 
19972264Sjacobs {
19982264Sjacobs 	int result = 0;
19992264Sjacobs 	int j;
20002264Sjacobs 
20012264Sjacobs 	/* ------- */
20022264Sjacobs 
20032264Sjacobs 	if ((attr != NULL) && (list != NULL))
20042264Sjacobs 	{
20052264Sjacobs 		for (j = 0; (list[j] != NULL) && (result != 1); j++)
20062264Sjacobs 		{
20072264Sjacobs 			if (strcasecmp(list[j], attr) == 0)
20082264Sjacobs 			{
20092264Sjacobs 				result = 1; /* found */
20102264Sjacobs 			}
20112264Sjacobs 		}
20122264Sjacobs 	}
20132264Sjacobs 
20142264Sjacobs 	return (result);
20152264Sjacobs } /* _attrInList */
20162264Sjacobs 
20172264Sjacobs 
20182264Sjacobs 
20192264Sjacobs 
20202264Sjacobs /*
20212264Sjacobs  * *****************************************************************************
20222264Sjacobs  *
20232264Sjacobs  * Function:    _attrInLDAPList()
20242264Sjacobs  *
20252264Sjacobs  * Description: Checks to see if the given attribute is an LDAP printing
20262264Sjacobs  *              attribute, ie. is either in an IPP objectclass or the
20272264Sjacobs  *              sun printer objectclass. Note: some attributes are handled
20282264Sjacobs  *              specifically outside this function, so are excluded from
20292264Sjacobs  *              the lists that are checked.
20302264Sjacobs  *
20312264Sjacobs  * Parameters:
20322264Sjacobs  * Input:       char *attr    - attribute to check
20332264Sjacobs  * Output:      None
20342264Sjacobs  *
20352264Sjacobs  * Returns:     int - TRUE = attr found in list
20362264Sjacobs  *
20372264Sjacobs  * *****************************************************************************
20382264Sjacobs  */
20392264Sjacobs 
20402264Sjacobs static int
_attrInLDAPList(char * attr)20412264Sjacobs _attrInLDAPList(char *attr)
20422264Sjacobs 
20432264Sjacobs {
20442264Sjacobs 	int result = 0;
20452264Sjacobs 
20462264Sjacobs 	/* ------- */
20472264Sjacobs 
20482264Sjacobs 	if (_attrInList(attr, nsl_attr_printerService))
20492264Sjacobs 	{
20502264Sjacobs 		result = 1;	/* in list */
20512264Sjacobs 	}
20522264Sjacobs 	else
20532264Sjacobs 	if (_attrInList(attr, nsl_attr_printerIPP))
20542264Sjacobs 	{
20552264Sjacobs 		result = 1;	/* in list */
20562264Sjacobs 	}
20572264Sjacobs 	else
20582264Sjacobs 	if (_attrInList(attr, nsl_attr_sunPrinter))
20592264Sjacobs 	{
20602264Sjacobs 		result = 1;	/* in list */
20612264Sjacobs 	}
20622264Sjacobs 
20632264Sjacobs 	return (result);
20642264Sjacobs } /* _attrInLDAPList */
20652264Sjacobs 
20662264Sjacobs 
20672264Sjacobs 
20682264Sjacobs 
20692264Sjacobs /*
20702264Sjacobs  * *****************************************************************************
20712264Sjacobs  *
20722264Sjacobs  * Function:    _getCurrentKVPValues()
20732264Sjacobs  *
20742264Sjacobs  * Description: For the given printer object read the current set of values
20752264Sjacobs  *              the object has for the sun-printer-kvp (Key Value pair)
20762264Sjacobs  *
20772264Sjacobs  * Parameters:
20782264Sjacobs  * Input:       LDAP *ld       - existing ldap connection descriptor
20792264Sjacobs  *              char *objectDN - DN to search for
20802264Sjacobs  * Output:      char ***list   - returned set of kvp values
20812264Sjacobs  *
20822264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists
20832264Sjacobs  *
20842264Sjacobs  * *****************************************************************************
20852264Sjacobs  */
20862264Sjacobs 
20872264Sjacobs static NSL_RESULT
_getCurrentKVPValues(LDAP * ld,uchar_t * objectDN,char *** list)20882264Sjacobs _getCurrentKVPValues(LDAP *ld, uchar_t *objectDN, char ***list)
20892264Sjacobs 
20902264Sjacobs {
20912264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
20922264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
20932264Sjacobs 	int i = 0;
20942264Sjacobs 	LDAPMessage *ldapMsg;
20952264Sjacobs 	char *requiredAttrs[2] = { ATTR_KVP, NULL };
20962264Sjacobs 	LDAPMessage *ldapEntry = NULL;
20972264Sjacobs 	char *entryAttrib = NULL;
20982264Sjacobs 	char **attribValues = NULL;
20992264Sjacobs 	BerElement *berElement = NULL;
21002264Sjacobs 
21012264Sjacobs 	/* ---------- */
21022264Sjacobs 
21032264Sjacobs 	if ((list != NULL) && (ld != NULL) && (objectDN != NULL))
21042264Sjacobs 	{
21052264Sjacobs 		/* search for this Printer in the directory */
21062264Sjacobs 
21072264Sjacobs 		sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE,
21082264Sjacobs 				"(objectclass=*)", requiredAttrs, 0, &ldapMsg);
21092264Sjacobs 		if (sresult == LDAP_SUCCESS)
21102264Sjacobs 		{
21112264Sjacobs 			/*
21122264Sjacobs 			 * check that the object exists and extract its
21132264Sjacobs 			 * KVP attribute values
21142264Sjacobs 			 */
21152264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
21162264Sjacobs 			if (ldapEntry != NULL)
21172264Sjacobs 			{
21182264Sjacobs 				entryAttrib = ldap_first_attribute(ld,
21192264Sjacobs 							ldapEntry, &berElement);
21202264Sjacobs 				if ((entryAttrib != NULL) &&
21212264Sjacobs 				    (strcasecmp(entryAttrib, ATTR_KVP) == 0))
21222264Sjacobs 
21232264Sjacobs 				{
21242264Sjacobs #ifdef DEBUG
21252264Sjacobs printf("Attribute: %s, its values are:\n", entryAttrib);
21262264Sjacobs #endif
21272264Sjacobs 					/*
21282264Sjacobs 					 * add each KVP value to the list
21292264Sjacobs 					 * that we will return
21302264Sjacobs 					 */
21312264Sjacobs 					attribValues = ldap_get_values(
21322264Sjacobs 						ld, ldapEntry, entryAttrib);
21332264Sjacobs 					for (i = 0;
21342264Sjacobs 						attribValues[i] != NULL; i++)
21352264Sjacobs 					{
21362264Sjacobs 					    *list = (char **)
21372264Sjacobs 						list_append((void **)*list,
21382264Sjacobs 						    strdup(attribValues[i]));
21392264Sjacobs #ifdef DEBUG
21402264Sjacobs printf("\t%s\n", attribValues[i]);
21412264Sjacobs #endif
21422264Sjacobs 					}
21432264Sjacobs 					(void) ldap_value_free(attribValues);
21442264Sjacobs 				}
21452264Sjacobs 
21462264Sjacobs 				if ((entryAttrib != NULL) &&
21472264Sjacobs 				    (berElement != NULL))
21482264Sjacobs 				{
21492264Sjacobs 					ber_free(berElement, 0);
21502264Sjacobs 				}
21512264Sjacobs 
21522264Sjacobs 
21532264Sjacobs 				/* object found */
21542264Sjacobs 				result = NSL_OK;
21552264Sjacobs 			}
21562264Sjacobs 
21572264Sjacobs 			(void) ldap_msgfree(ldapMsg);
21582264Sjacobs 		}
21592264Sjacobs 	}
21602264Sjacobs 
21612264Sjacobs 	else
21622264Sjacobs 	{
21632264Sjacobs 		result = NSL_ERR_INTERNAL;
21642264Sjacobs 	}
21652264Sjacobs 
21662264Sjacobs 	return (result);
21672264Sjacobs } /* _getCurrentKVPValues */
21682264Sjacobs 
21692264Sjacobs 
21702264Sjacobs 
21712264Sjacobs /*
21722264Sjacobs  * *****************************************************************************
21732264Sjacobs  *
21742264Sjacobs  * Function:    _freeList()
21752264Sjacobs  *
21762264Sjacobs  * Description: Free the list created by list_append() where the items in
21772264Sjacobs  *              the list have been strdup'ed.
21782264Sjacobs  *
21792264Sjacobs  * Parameters:
21802264Sjacobs  * Input:       char ***list   - returned set of kvp values
21812264Sjacobs  *
21822264Sjacobs  * Result:      void
21832264Sjacobs  *
21842264Sjacobs  * *****************************************************************************
21852264Sjacobs  */
21862264Sjacobs 
21872264Sjacobs static void
_freeList(char *** list)21882264Sjacobs _freeList(char ***list)
21892264Sjacobs 
21902264Sjacobs {
21912264Sjacobs 	int i = 0;
21922264Sjacobs 
21932264Sjacobs 	/* ------ */
21942264Sjacobs 
21952264Sjacobs 	if (list != NULL)
21962264Sjacobs 	{
21972264Sjacobs 		if (*list != NULL)
21982264Sjacobs 		{
21992264Sjacobs 			for (i = 0; (*list)[i] != NULL; i++)
22002264Sjacobs 			{
22012264Sjacobs 				free((*list)[i]);
22022264Sjacobs 			}
22032264Sjacobs 			free(*list);
22042264Sjacobs 		}
22052264Sjacobs 
22062264Sjacobs 		*list = NULL;
22072264Sjacobs 	}
22082264Sjacobs } /* _freeList */
22092264Sjacobs 
22102264Sjacobs 
22112264Sjacobs 
22122264Sjacobs /*
22132264Sjacobs  * *****************************************************************************
22142264Sjacobs  *
22152264Sjacobs  * Function:    _modAttrKVP()
22162264Sjacobs  *
22172264Sjacobs  * Description: Sort out the KVP attribute value list, such that this new
22182264Sjacobs  *              value takes precidence over any existing value in the list.
22192264Sjacobs  *              The current list is updated to remove this key, and the new
22202264Sjacobs  *              key "value" is added to the list, eg. for
22212264Sjacobs  *                  value: bbb=ddddd
22222264Sjacobs  *                  and kvpList:
22232264Sjacobs  *                         aaa=yyyy
22242264Sjacobs  *                         bbb=zzzz
22252264Sjacobs  *                         ccc=xxxx
22262264Sjacobs  *                  the resulting kvpList is:
22272264Sjacobs  *                         aaa=yyyy
22282264Sjacobs  *                         ccc=xxxx
22292264Sjacobs  *                         bbb=ddddd
22302264Sjacobs  *
22312264Sjacobs  * Note:        When all new values have been handled the function _attrAddKVP()
22322264Sjacobs  *              must be called to add the "new list" values into the
22332264Sjacobs  *              LDAPMod array.
22342264Sjacobs  *
22352264Sjacobs  * Parameters:
22362264Sjacobs  * Input:       char *value       - Key Value Pair to process,
22372264Sjacobs  *                                  eg. aaaaa=hhhhh, where aaaaa is the key
22382264Sjacobs  *              char ***kvpList   - list of current KVP values
22392264Sjacobs  * Output:      char ***kvpList   - updated list of KVP values
22402264Sjacobs  *
22412264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = done okay
22422264Sjacobs  *
22432264Sjacobs  * *****************************************************************************
22442264Sjacobs  */
22452264Sjacobs 
22462264Sjacobs static NSL_RESULT
_modAttrKVP(char * value,char *** kvpList)22472264Sjacobs _modAttrKVP(char *value, char ***kvpList)
22482264Sjacobs 
22492264Sjacobs {
22502264Sjacobs 	NSL_RESULT result = NSL_ERR_INTERNAL;
22512264Sjacobs 	int i = 0;
22522264Sjacobs 	int inList = 0;
22532264Sjacobs 	int keyDelete = 0;
22542264Sjacobs 	char *key = NULL;
22552264Sjacobs 	char **p = NULL;
22562264Sjacobs 	char **newList = NULL;
22572264Sjacobs 
22582264Sjacobs 	/* ------- */
22592264Sjacobs 
22602264Sjacobs 	if ((value != NULL) && (kvpList != NULL))
22612264Sjacobs 	{
22622264Sjacobs 		result = NSL_OK;
22632264Sjacobs 
22642264Sjacobs 		/* extract "key" from value */
22652264Sjacobs 
22662264Sjacobs 		key = strdup(value);
22672264Sjacobs 
22682264Sjacobs 		for (i = 0; ((key)[i] != '=') && ((key)[i] != '\0'); i++);
22692264Sjacobs 		key[i] = '\0'; /* terminate the key */
22702264Sjacobs 
22712264Sjacobs 		/* Is this a request to delete a "key" value */
22722264Sjacobs 
22732264Sjacobs 		if ((value[i] == '\0') || (value[i+1] == '\0'))
22742264Sjacobs 		{
22752264Sjacobs 			/* this is a request to delete the key */
22762264Sjacobs 			keyDelete = 1;
22772264Sjacobs 		}
22782264Sjacobs 
22792264Sjacobs 		if ((*kvpList != NULL) && (**kvpList != NULL))
22802264Sjacobs 		{
22812264Sjacobs 			/*
22822264Sjacobs 			 * for each item in the list remove it if the keys match
22832264Sjacobs 			 */
22842264Sjacobs 			for (p = *kvpList; *p != NULL; p++)
22852264Sjacobs 			{
22862264Sjacobs 				for (i = 0;
22872264Sjacobs 				    ((*p)[i] != '=') && ((*p)[i] != '\0'); i++);
22882264Sjacobs 
22892264Sjacobs 				if ((strlen(key) == i) &&
22902264Sjacobs 					(strncasecmp(*p, key, i) == 0))
22912264Sjacobs 				{
22922264Sjacobs 					inList = 1;
22932264Sjacobs 				}
22942264Sjacobs 				else
22952264Sjacobs 				{
22962264Sjacobs 					/* no match so add value to new list */
22972264Sjacobs 					newList = (char **)list_append(
22982264Sjacobs 							(void **)newList,
22992264Sjacobs 							strdup(*p));
23002264Sjacobs 				}
23012264Sjacobs 			}
23022264Sjacobs 		}
23032264Sjacobs 
23042264Sjacobs 		/*
23052264Sjacobs 		 * if it was not a DELETE request add the new key value into
23062264Sjacobs 		 * the newList, otherwise we have already removed the key
23072264Sjacobs 		 */
23082264Sjacobs 
23092264Sjacobs 		if (!keyDelete)
23102264Sjacobs 		{
23112264Sjacobs 			newList = (char **)list_append((void **)newList,
23122264Sjacobs 							strdup(value));
23132264Sjacobs 		}
23142264Sjacobs 
23152264Sjacobs 		if ((newList != NULL) || (inList))
23162264Sjacobs 		{
23172264Sjacobs 			/* replace old list with the newList */
23182264Sjacobs 			_freeList(kvpList);
23192264Sjacobs 			*kvpList = newList;
23202264Sjacobs 		}
23212264Sjacobs 
23222264Sjacobs 		free(key);
23232264Sjacobs 	}
23242264Sjacobs 
23252264Sjacobs 	return (result);
23262264Sjacobs } /* modAttrKVP */
23272264Sjacobs 
23282264Sjacobs 
23292264Sjacobs 
23302264Sjacobs 
23312264Sjacobs /*
23322264Sjacobs  * *****************************************************************************
23332264Sjacobs  *
23342264Sjacobs  * Function:    _attrAddKVP()
23352264Sjacobs  *
23362264Sjacobs  * Description: Process KVP items in the kvpList adding them to the
23372264Sjacobs  *              LDAPMod modify array. If the list is empty but there were
23382264Sjacobs  *              previously LDAP KVP values delete them.
23392264Sjacobs  *
23402264Sjacobs  * Note:        This function should only be called when all the new KVP
23412264Sjacobs  *              items have been processed by _modAttrKVP()
23422264Sjacobs  *
23432264Sjacobs  * Parameters:
23442264Sjacobs  * Input:       LDAPMod ***attrs - array to update
23452264Sjacobs  *              char **kvpList   - list KVP values
23462264Sjacobs  *              int  kvpExists   - object currently has LDAP KVP values
23472264Sjacobs  * Output:      None
23482264Sjacobs  *
23492264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = done okay
23502264Sjacobs  *
23512264Sjacobs  * *****************************************************************************
23522264Sjacobs  */
23532264Sjacobs 
23542264Sjacobs static NSL_RESULT
_attrAddKVP(LDAPMod *** attrs,char ** kvpList,int kvpExists)23552264Sjacobs _attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists)
23562264Sjacobs 
23572264Sjacobs {
23582264Sjacobs 	NSL_RESULT result = NSL_OK;
23592264Sjacobs 
23602264Sjacobs 	/* ------- */
23612264Sjacobs 
23622264Sjacobs 	if (attrs != NULL)
23632264Sjacobs 	{
23642264Sjacobs 		if (kvpList != NULL)
23652264Sjacobs 		{
23662264Sjacobs 			while ((kvpList != NULL) && (*kvpList != NULL))
23672264Sjacobs 			{
23682264Sjacobs 				/* add item to LDAPMod array */
23692264Sjacobs 
23702264Sjacobs 				result =
23712264Sjacobs 				    _modLDAPmodValue(attrs, ATTR_KVP, *kvpList);
23722264Sjacobs 
23732264Sjacobs 				kvpList++;
23742264Sjacobs 			}
23752264Sjacobs 		}
23762264Sjacobs 		else
23772264Sjacobs 		if (kvpExists)
23782264Sjacobs 		{
23792264Sjacobs 			/*
23802264Sjacobs 			 * We now have no LDAP KVP values but there were
23812264Sjacobs 			 * some previously, so delete them
23822264Sjacobs 			 */
23832264Sjacobs 			result = _modLDAPmodValue(attrs, ATTR_KVP, NULL);
23842264Sjacobs 		}
23852264Sjacobs 	}
23862264Sjacobs 
23872264Sjacobs 	else
23882264Sjacobs 	{
23892264Sjacobs 		result = NSL_ERR_INTERNAL;
23902264Sjacobs 	}
23912264Sjacobs 
23922264Sjacobs 	return (result);
23932264Sjacobs } /* _attrAddKVP */
23942264Sjacobs 
23952264Sjacobs 
23962264Sjacobs 
23972264Sjacobs 
23982264Sjacobs /*
23992264Sjacobs  * *****************************************************************************
24002264Sjacobs  *
24012264Sjacobs  * Function:    _manageReferralCredentials()
24022264Sjacobs  *
24032264Sjacobs  * Description: This function is called if a referral request is returned by
24042264Sjacobs  *              the origonal LDAP server during the ldap update request call,
24052264Sjacobs  *              eg. ldap_add_s(), ldap_modify_s() or ldap_delete_s().
24062264Sjacobs  * Parameters:
24072264Sjacobs  * Input:       LDAP *ld      - LDAP descriptor
24082264Sjacobs  *              int freeit    - 0 = first call to get details
24092264Sjacobs  *                            - 1 = second call to free details
24102264Sjacobs  *                            - -1 = initial store of authentication details
24112264Sjacobs  * Input/Output: char **dn    - returns DN to bind to on master
24122264Sjacobs  *               char **credp - returns password for DN
24132264Sjacobs  *               int *methodp - returns authentication type, eg. simple
24142264Sjacobs  *
24152264Sjacobs  * Returns:     int - 0 = okay
24162264Sjacobs  *
24172264Sjacobs  * *****************************************************************************
24182264Sjacobs  */
_manageReferralCredentials(LDAP * ld,char ** dn,char ** credp,int * methodp,int freeit)24192264Sjacobs static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp,
24202264Sjacobs 					int *methodp, int freeit)
24212264Sjacobs 
24222264Sjacobs {
24232264Sjacobs 	int result = 0;
24242264Sjacobs 	static char *sDN = NULL;
24252264Sjacobs 	static char *sPasswd = NULL;
24262264Sjacobs 	static int  sMethod = LDAP_AUTH_SIMPLE;
24272264Sjacobs 
24282264Sjacobs 	/* -------- */
24292264Sjacobs 
24302264Sjacobs 	if (freeit == 1)
24312264Sjacobs 	{
24322264Sjacobs 		/* second call - free memory */
24332264Sjacobs 
24342264Sjacobs 		if ((dn != NULL) && (*dn != NULL))
24352264Sjacobs 		{
24362264Sjacobs 			free(*dn);
24372264Sjacobs 		}
24382264Sjacobs 
24392264Sjacobs 		if ((credp != NULL) && (*credp != NULL))
24402264Sjacobs 		{
24412264Sjacobs 			free(*credp);
24422264Sjacobs 		}
24432264Sjacobs 	}
24442264Sjacobs 
24452264Sjacobs 	else
24462264Sjacobs 	if ((ld != NULL) &&
24472264Sjacobs 	    (dn != NULL) && (credp != NULL) && (methodp != NULL))
24482264Sjacobs 	{
24492264Sjacobs 		if ((freeit == 0) && (sDN != NULL) && (sPasswd != NULL))
24502264Sjacobs 		{
24512264Sjacobs 			/* first call - get the saved bind credentials */
24522264Sjacobs 
24532264Sjacobs 			*dn = strdup(sDN);
24542264Sjacobs 			*credp = strdup(sPasswd);
24552264Sjacobs 			*methodp = sMethod;
24562264Sjacobs 		}
24572264Sjacobs 		else
24582264Sjacobs 		if (freeit == -1)
24592264Sjacobs 		{
24602264Sjacobs 			/* initial call - save the saved bind credentials */
24612264Sjacobs 
24622264Sjacobs 			sDN = *dn;
24632264Sjacobs 			sPasswd = *credp;
24642264Sjacobs 			sMethod = *methodp;
24652264Sjacobs 		}
24662264Sjacobs 		else
24672264Sjacobs 		{
24682264Sjacobs 			result = 1;	/* error */
24692264Sjacobs 		}
24702264Sjacobs 	}
24712264Sjacobs 	else
24722264Sjacobs 	{
24732264Sjacobs 		result = 1;	/* error */
24742264Sjacobs 	}
24752264Sjacobs 
24762264Sjacobs 	return (result);
24772264Sjacobs } /* _manageReferralCredentials */
2478