1*2264Sjacobs /*
2*2264Sjacobs  * CDDL HEADER START
3*2264Sjacobs  *
4*2264Sjacobs  * The contents of this file are subject to the terms of the
5*2264Sjacobs  * Common Development and Distribution License (the "License").
6*2264Sjacobs  * You may not use this file except in compliance with the License.
7*2264Sjacobs  *
8*2264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2264Sjacobs  * or http://www.opensolaris.org/os/licensing.
10*2264Sjacobs  * See the License for the specific language governing permissions
11*2264Sjacobs  * and limitations under the License.
12*2264Sjacobs  *
13*2264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
14*2264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
16*2264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
17*2264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2264Sjacobs  *
19*2264Sjacobs  * CDDL HEADER END
20*2264Sjacobs  */
21*2264Sjacobs /*
22*2264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*2264Sjacobs  * Use is subject to license terms.
24*2264Sjacobs  */
25*2264Sjacobs 
26*2264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*2264Sjacobs 
28*2264Sjacobs #include <stdio.h>
29*2264Sjacobs #include <stdlib.h>
30*2264Sjacobs #include <unistd.h>
31*2264Sjacobs #include <sys/types.h>
32*2264Sjacobs #include <sys/stat.h>
33*2264Sjacobs #include <string.h>
34*2264Sjacobs #include <stdarg.h>
35*2264Sjacobs #include <fcntl.h>
36*2264Sjacobs #include <syslog.h>
37*2264Sjacobs #include <errno.h>
38*2264Sjacobs #include <pwd.h>
39*2264Sjacobs #include <libintl.h>
40*2264Sjacobs #include <netdb.h>	/* for rcmd() */
41*2264Sjacobs 
42*2264Sjacobs #include <ns.h>
43*2264Sjacobs #include <list.h>
44*2264Sjacobs #include <misc.h>
45*2264Sjacobs 
46*2264Sjacobs #define	LDAP_REFERRALS
47*2264Sjacobs #include <lber.h>
48*2264Sjacobs #include <ldap.h>
49*2264Sjacobs #include <sys/systeminfo.h>
50*2264Sjacobs 
51*2264Sjacobs 
52*2264Sjacobs /*
53*2264Sjacobs  * This modules contains the code required to manipulate printer objects in
54*2264Sjacobs  * a LDAP directory for the Naming Service (NS) switch.
55*2264Sjacobs  * It can "add", "modify" and "delete" the objects on the given ldap server
56*2264Sjacobs  * and in the given NS domain DN, eg. "dc=mkg,dc=sun,dc=com".
57*2264Sjacobs  * Note: printers known to the naming service are contained in the RDN
58*2264Sjacobs  * "ou=printers" under the NS domain DN
59*2264Sjacobs  */
60*2264Sjacobs 
61*2264Sjacobs #define	PCONTAINER	"ou=printers"
62*2264Sjacobs 
63*2264Sjacobs /* attribute keywords */
64*2264Sjacobs #define	ATTR_DN		"dn"
65*2264Sjacobs #define	ATTR_OCLASS	"objectClass"
66*2264Sjacobs #define	ATTR_URI	"printer-uri"
67*2264Sjacobs #define	ATTR_PNAME	"printer-name"
68*2264Sjacobs #define	ATTR_XRISUP	"printer-xri-supported"
69*2264Sjacobs #define	ATTR_BSDADDR	"sun-printer-bsdaddr"
70*2264Sjacobs #define	ATTR_KVP	"sun-printer-kvp"
71*2264Sjacobs 
72*2264Sjacobs /* objectClass values */
73*2264Sjacobs #define	OCV_TOP		"top"
74*2264Sjacobs #define	OCV_PSERVICE	"printerService"
75*2264Sjacobs #define	OCV_SUNPRT	"sunPrinter"
76*2264Sjacobs #define	OCV_PABSTRACT	"printerAbstract"
77*2264Sjacobs 
78*2264Sjacobs /* xri-supported attribute value */
79*2264Sjacobs #define	AV_UNKNOWN	"unknown"
80*2264Sjacobs 
81*2264Sjacobs 
82*2264Sjacobs /*
83*2264Sjacobs  * LDAP objectclass atributes that the user can explicity change
84*2264Sjacobs  */
85*2264Sjacobs 
86*2264Sjacobs static const char *nsl_attr_printerService[] = {
87*2264Sjacobs 	"printer-uri",
88*2264Sjacobs 	"printer-xri-supported",
89*2264Sjacobs 	/* Not allowed "printer-name", */
90*2264Sjacobs 	"printer-natural-language-configured",
91*2264Sjacobs 	"printer-location",
92*2264Sjacobs 	"printer-info",
93*2264Sjacobs 	"printer-more-info",
94*2264Sjacobs 	"printer-make-and-model",
95*2264Sjacobs 	"printer-charset-configured",
96*2264Sjacobs 	"printer-charset-supported",
97*2264Sjacobs 	"printer-generated-natural-language-supported",
98*2264Sjacobs 	"printer-document-format-supported",
99*2264Sjacobs 	"printer-color-supported",
100*2264Sjacobs 	"printer-compression-supported",
101*2264Sjacobs 	"printer-pages-per-minute",
102*2264Sjacobs 	"printer-pages-per-minute-color",
103*2264Sjacobs 	"printer-finishings-supported",
104*2264Sjacobs 	"printer-number-up-supported",
105*2264Sjacobs 	"printer-sides-supported",
106*2264Sjacobs 	"printer-media-supported",
107*2264Sjacobs 	"printer-media-local-supported",
108*2264Sjacobs 	"printer-resolution-supported",
109*2264Sjacobs 	"printer-print-quality-supported",
110*2264Sjacobs 	"printer-job-priority-supported",
111*2264Sjacobs 	"printer-copies-supported",
112*2264Sjacobs 	"printer-job-k-octets-supported",
113*2264Sjacobs 	"printer-current-operator",
114*2264Sjacobs 	"printer-service-person",
115*2264Sjacobs 	"printer-delivery-orientation-supported",
116*2264Sjacobs 	"printer-stacking-order-supported",
117*2264Sjacobs 	"printer-output-features-supported",
118*2264Sjacobs 	(char *)NULL
119*2264Sjacobs };
120*2264Sjacobs 
121*2264Sjacobs 
122*2264Sjacobs static const char *nsl_attr_printerIPP[] = {
123*2264Sjacobs 	"printer-ipp-versions-supported",
124*2264Sjacobs 	"printer-multiple-document-jobs-supported",
125*2264Sjacobs 	(char *)NULL
126*2264Sjacobs };
127*2264Sjacobs 
128*2264Sjacobs static const char *nsl_attr_sunPrinter[] = {
129*2264Sjacobs 	/* Not allowed "sun-printer-bsdaddr", */
130*2264Sjacobs 	/* Not allowed "sun-printer-kvp", */
131*2264Sjacobs 	(char *)NULL
132*2264Sjacobs };
133*2264Sjacobs 
134*2264Sjacobs 
135*2264Sjacobs /*
136*2264Sjacobs  * List of LDAP attributes that user is not allowed to explicitly change
137*2264Sjacobs  */
138*2264Sjacobs static const char *nsl_attr_notAllowed[] = {
139*2264Sjacobs 	ATTR_DN,
140*2264Sjacobs 	ATTR_OCLASS,		/* objectclass */
141*2264Sjacobs 	ATTR_PNAME,		/* printer-name */
142*2264Sjacobs 	ATTR_BSDADDR,
143*2264Sjacobs 	ATTR_KVP,
144*2264Sjacobs 	(char *)NULL
145*2264Sjacobs };
146*2264Sjacobs 
147*2264Sjacobs 
148*2264Sjacobs static NSL_RESULT _connectToLDAP(ns_cred_t *cred, LDAP **ld);
149*2264Sjacobs static uchar_t *_constructPrinterDN(uchar_t *printerName,
150*2264Sjacobs 				uchar_t *domainDN, char **attrList);
151*2264Sjacobs static NSL_RESULT _checkPrinterExists(LDAP *ld, uchar_t *printerName,
152*2264Sjacobs 			uchar_t *domainDN, uchar_t **printerDN);
153*2264Sjacobs static NSL_RESULT _checkPrinterDNExists(LDAP *ld, uchar_t *objectDN);
154*2264Sjacobs static NSL_RESULT _checkSunPrinter(LDAP *ld, uchar_t *printerDN);
155*2264Sjacobs static NSL_RESULT _addNewPrinterObject(LDAP *ld, uchar_t *printerName,
156*2264Sjacobs 					uchar_t *domainDN, char **attrList);
157*2264Sjacobs static NSL_RESULT _modifyPrinterObject(LDAP *ld, uchar_t *printerDN,
158*2264Sjacobs 		uchar_t *printerName, uchar_t *domainDN, char **attrList);
159*2264Sjacobs static NSL_RESULT _checkAttributes(char **list);
160*2264Sjacobs static NSL_RESULT _addLDAPmodValue(LDAPMod ***attrs, char *type, char *value);
161*2264Sjacobs static NSL_RESULT _modLDAPmodValue(LDAPMod ***attrs, char *type, char *value);
162*2264Sjacobs static NSL_RESULT _constructAddLDAPMod(uchar_t *printerName,
163*2264Sjacobs 					char **attrList,  LDAPMod ***attrs);
164*2264Sjacobs static NSL_RESULT _constructModLDAPMod(uchar_t *printerName, int sunPrinter,
165*2264Sjacobs 			char **attrList, char ***oldKVPList, LDAPMod ***attrs);
166*2264Sjacobs static NSL_RESULT _compareURIinDNs(uchar_t *dn1, uchar_t *dn2);
167*2264Sjacobs static uchar_t *_getThisNSDomainDN(void);
168*2264Sjacobs static int _popen(char *cmd, char *results, int size);
169*2264Sjacobs static int _attrInList(char *attr, const char **list);
170*2264Sjacobs static int _attrInLDAPList(char *attr);
171*2264Sjacobs static NSL_RESULT _getCurrentKVPValues(LDAP *ld,
172*2264Sjacobs 					uchar_t *objectDN, char ***list);
173*2264Sjacobs static void _freeList(char ***list);
174*2264Sjacobs static NSL_RESULT _modAttrKVP(char *value, char ***kvpList);
175*2264Sjacobs static NSL_RESULT _attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists);
176*2264Sjacobs static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp,
177*2264Sjacobs 					int *methodp, int freeit);
178*2264Sjacobs 
179*2264Sjacobs /*
180*2264Sjacobs  * *****************************************************************************
181*2264Sjacobs  *
182*2264Sjacobs  * Function:    ldap_put_printer()
183*2264Sjacobs  *
184*2264Sjacobs  * Description: Action the request to change a printer object in the LDAP
185*2264Sjacobs  *              directory DIT. The object is either added, modified or deleted
186*2264Sjacobs  *              depending on the request's attribute list. A null list indicates
187*2264Sjacobs  *              the request is a delete.
188*2264Sjacobs  *              The object's DN is constructed from the supplied domain DN and
189*2264Sjacobs  *              a check is done to see if the object exists already, if it
190*2264Sjacobs  *              doesn't exist then this is a request to add a new object
191*2264Sjacobs  *              If a URI is given in the attribute list and it is different to
192*2264Sjacobs  *              the existing printing object's DN then the request will be
193*2264Sjacobs  *              rejected.
194*2264Sjacobs  *
195*2264Sjacobs  *
196*2264Sjacobs  * Parameters:
197*2264Sjacobs  * Input:       const ns_printer_t *printer
198*2264Sjacobs  *                - this structure contains the following :
199*2264Sjacobs  *                  char *printerName - name of the printer
200*2264Sjacobs  *                  ns_cred_t *cred - structure containing the ldap host and
201*2264Sjacobs  *                                port, user, password and NS domain DN for the
202*2264Sjacobs  *                                directory server to be updated.
203*2264Sjacobs  *                  char **attrList - pointer to a list of attribute key values
204*2264Sjacobs  *                                for the printer object. If the object does
205*2264Sjacobs  *                                not already exist then this list contains the
206*2264Sjacobs  *                                values for the new object, otherwise this list
207*2264Sjacobs  *                                is a list of attributes to modify. For modify
208*2264Sjacobs  *                                a null attribute value is a attribute delete
209*2264Sjacobs  *                                request. A NULL ptr = delete the object.
210*2264Sjacobs  * Output:      None
211*2264Sjacobs  *
212*2264Sjacobs  * Returns:     int - 0 = request actioned okay
213*2264Sjacobs  *                   !0 = error - see NSL_RESULT codes
214*2264Sjacobs  *
215*2264Sjacobs  * *****************************************************************************
216*2264Sjacobs  */
217*2264Sjacobs 
218*2264Sjacobs int
219*2264Sjacobs ldap_put_printer(const ns_printer_t *printer)
220*2264Sjacobs 
221*2264Sjacobs {
222*2264Sjacobs 	NSL_RESULT result = NSL_OK;
223*2264Sjacobs 	NSL_RESULT printerExists = NSL_ERR_UNKNOWN_PRINTER;
224*2264Sjacobs 	LDAP *ld = NULL;
225*2264Sjacobs 	uchar_t *printerDN = NULL;
226*2264Sjacobs 	uchar_t *domainDN = NULL;
227*2264Sjacobs 	char *printerName = NULL;
228*2264Sjacobs 	ns_cred_t *cred = NULL;
229*2264Sjacobs 	char **attrList = NULL;
230*2264Sjacobs 
231*2264Sjacobs 	/* -------- */
232*2264Sjacobs 
233*2264Sjacobs 	/*
234*2264Sjacobs 	 * Note: the "attributes" list should be null for ldap as the attribute
235*2264Sjacobs 	 * values are passed in the nsdata field
236*2264Sjacobs 	 */
237*2264Sjacobs 
238*2264Sjacobs 	if ((printer != NULL) &&
239*2264Sjacobs 	    (printer->attributes == NULL) && (printer->name != NULL))
240*2264Sjacobs 	{
241*2264Sjacobs 		/* extract required pointer values from structure */
242*2264Sjacobs 
243*2264Sjacobs 		printerName = printer->name;
244*2264Sjacobs 		cred = printer->cred;
245*2264Sjacobs 		if (printer->nsdata != NULL)
246*2264Sjacobs 		{
247*2264Sjacobs 			attrList = ((NS_LDAPDATA *)(printer->nsdata))->attrList;
248*2264Sjacobs 		}
249*2264Sjacobs 
250*2264Sjacobs 		/* connect and bind to the ldap directory server */
251*2264Sjacobs 
252*2264Sjacobs 		result = _connectToLDAP(cred, &ld);
253*2264Sjacobs 		if ((result == NSL_OK) && (ld != NULL))
254*2264Sjacobs 		{
255*2264Sjacobs 			/*
256*2264Sjacobs 			 * check if the NS domain DN was given, if not use the
257*2264Sjacobs 			 * current NS domain
258*2264Sjacobs 			 */
259*2264Sjacobs 
260*2264Sjacobs 			if (cred->domainDN != NULL)
261*2264Sjacobs 			{
262*2264Sjacobs 				domainDN = (uchar_t *)
263*2264Sjacobs 					strdup((char *)cred->domainDN);
264*2264Sjacobs 			}
265*2264Sjacobs 			else
266*2264Sjacobs 			{
267*2264Sjacobs 				/* get DN of current domain */
268*2264Sjacobs 				domainDN = _getThisNSDomainDN();
269*2264Sjacobs 			}
270*2264Sjacobs 
271*2264Sjacobs 			printerExists =
272*2264Sjacobs 				_checkPrinterExists(ld, (uchar_t *)printerName,
273*2264Sjacobs 							domainDN, &printerDN);
274*2264Sjacobs 			if (printerExists != LDAP_SUCCESS)
275*2264Sjacobs 			{
276*2264Sjacobs 				/*
277*2264Sjacobs 				 * could not find the printer by printer-name,
278*2264Sjacobs 				 * but there could be a non sunPrinter object
279*2264Sjacobs 				 * so if the printer-uri was given check if
280*2264Sjacobs 				 * an object for that exists
281*2264Sjacobs 				 */
282*2264Sjacobs 				printerDN =
283*2264Sjacobs 				    _constructPrinterDN(NULL,
284*2264Sjacobs 							domainDN, attrList);
285*2264Sjacobs 				if (printerDN != NULL)
286*2264Sjacobs 				{
287*2264Sjacobs 					printerExists = _checkPrinterDNExists(
288*2264Sjacobs 								ld, printerDN);
289*2264Sjacobs 				}
290*2264Sjacobs 			}
291*2264Sjacobs #ifdef DEBUG
292*2264Sjacobs if (printerExists == NSL_OK)
293*2264Sjacobs {
294*2264Sjacobs printf("DN found = '%s' for '%s'\n", printerDN, printerName);
295*2264Sjacobs }
296*2264Sjacobs #endif
297*2264Sjacobs 
298*2264Sjacobs 			if (attrList == NULL)
299*2264Sjacobs 			{
300*2264Sjacobs 				/*
301*2264Sjacobs 				 * a null list indicates that this is a DELETE
302*2264Sjacobs 				 * object request, so if object exists delete
303*2264Sjacobs 				 * it, otherwise report an error.
304*2264Sjacobs 				 */
305*2264Sjacobs 				if (printerExists == LDAP_SUCCESS)
306*2264Sjacobs 				{
307*2264Sjacobs 				    result = ldap_delete_s(ld,
308*2264Sjacobs 						(char *)printerDN);
309*2264Sjacobs 				    if (result != LDAP_SUCCESS)
310*2264Sjacobs 				    {
311*2264Sjacobs 					result = NSL_ERR_DEL_FAILED;
312*2264Sjacobs #ifdef DEBUG
313*2264Sjacobs ldap_perror(ld, "ldap_delete_s failed");
314*2264Sjacobs #endif
315*2264Sjacobs 				    }
316*2264Sjacobs 				}
317*2264Sjacobs 				else
318*2264Sjacobs 				{
319*2264Sjacobs 				    result = NSL_ERR_UNKNOWN_PRINTER;
320*2264Sjacobs 				}
321*2264Sjacobs 			}
322*2264Sjacobs 			else
323*2264Sjacobs 			{
324*2264Sjacobs 				/*
325*2264Sjacobs 				 * if object exists then this is a
326*2264Sjacobs 				 * modify request otherwise is is an add request
327*2264Sjacobs 				 */
328*2264Sjacobs 
329*2264Sjacobs 				if (printerExists == LDAP_SUCCESS)
330*2264Sjacobs 				{
331*2264Sjacobs 					/*
332*2264Sjacobs 					 * Modify the printer object to
333*2264Sjacobs 					 * give it the new attribute values
334*2264Sjacobs 					 * specified by the user
335*2264Sjacobs 					 */
336*2264Sjacobs 					result =
337*2264Sjacobs 					_modifyPrinterObject(ld, printerDN,
338*2264Sjacobs 						(uchar_t *)printerName,
339*2264Sjacobs 						domainDN, attrList);
340*2264Sjacobs 				}
341*2264Sjacobs 				else
342*2264Sjacobs 				{
343*2264Sjacobs 					/*
344*2264Sjacobs 					 * add new printer object into the
345*2264Sjacobs 					 * ldap directory with the user
346*2264Sjacobs 					 * specified attribute values
347*2264Sjacobs 					 */
348*2264Sjacobs 					result =
349*2264Sjacobs 					    _addNewPrinterObject(ld,
350*2264Sjacobs 						(uchar_t *)printerName,
351*2264Sjacobs 						domainDN, attrList);
352*2264Sjacobs 				}
353*2264Sjacobs 			}
354*2264Sjacobs 
355*2264Sjacobs 			if (printerDN != NULL)
356*2264Sjacobs 			{
357*2264Sjacobs 				free(printerDN);
358*2264Sjacobs 			}
359*2264Sjacobs 			if (domainDN != NULL)
360*2264Sjacobs 			{
361*2264Sjacobs 				free(domainDN);
362*2264Sjacobs 			}
363*2264Sjacobs 
364*2264Sjacobs 			/* disconnect from LDAP server */
365*2264Sjacobs 
366*2264Sjacobs 			(void) ldap_unbind(ld);
367*2264Sjacobs 		}
368*2264Sjacobs 	}
369*2264Sjacobs 
370*2264Sjacobs 	else
371*2264Sjacobs 	{
372*2264Sjacobs 		/* no printerName given */
373*2264Sjacobs 		result = NSL_ERR_INTERNAL;
374*2264Sjacobs 	}
375*2264Sjacobs 
376*2264Sjacobs 	return ((int)result);
377*2264Sjacobs } /* ldap_put_printer */
378*2264Sjacobs 
379*2264Sjacobs 
380*2264Sjacobs 
381*2264Sjacobs 
382*2264Sjacobs /*
383*2264Sjacobs  * *****************************************************************************
384*2264Sjacobs  *
385*2264Sjacobs  * Function:    _connectToLDAP()
386*2264Sjacobs  *
387*2264Sjacobs  * Description: Setup the connection and bind to the LDAP directory server.
388*2264Sjacobs  *              The function returns the ldap connection descriptor
389*2264Sjacobs  *
390*2264Sjacobs  * Note:        Currently the native ldap functions do not support secure
391*2264Sjacobs  *              passwords, when this is supported this function will require
392*2264Sjacobs  *              updating to allow the type passed in cred->passwdType to
393*2264Sjacobs  *              be used with the ldap_simple_bind()
394*2264Sjacobs  *
395*2264Sjacobs  * Parameters:
396*2264Sjacobs  * Input:       ns_cred_t *cred - structure containing the credentials (host,
397*2264Sjacobs  *                                port, user and password) required to bind
398*2264Sjacobs  *                                to the directory server to be updated.
399*2264Sjacobs  *              char *printerName - printer name used only for error messages
400*2264Sjacobs  * Output:      LDAP** - ldap connection descriptor pointer. NULL = failed
401*2264Sjacobs  *
402*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = connected okay
403*2264Sjacobs  *
404*2264Sjacobs  * *****************************************************************************
405*2264Sjacobs  */
406*2264Sjacobs 
407*2264Sjacobs static NSL_RESULT
408*2264Sjacobs _connectToLDAP(ns_cred_t *cred, LDAP **ld)
409*2264Sjacobs 
410*2264Sjacobs {
411*2264Sjacobs 	NSL_RESULT result = NSL_OK;
412*2264Sjacobs 	int lresult = 0;
413*2264Sjacobs 	int ldapPort = LDAP_PORT;	/* default LDAP port number */
414*2264Sjacobs 	int protoVersion = LDAP_VERSION3;
415*2264Sjacobs 	int derefOption = LDAP_DEREF_NEVER;
416*2264Sjacobs 	int referrals = 1;
417*2264Sjacobs 	char hostname[MAXHOSTNAMELEN];
418*2264Sjacobs 	int tmpMethod = LDAP_AUTH_SIMPLE; /* temp - until its passed in */
419*2264Sjacobs 
420*2264Sjacobs 	/* -------- */
421*2264Sjacobs 
422*2264Sjacobs 	if ((ld == NULL) || (cred == NULL) ||
423*2264Sjacobs 		((cred->passwd == NULL) || (cred->binddn == NULL)))
424*2264Sjacobs 	{
425*2264Sjacobs 		result = NSL_ERR_CREDENTIALS;
426*2264Sjacobs 	}
427*2264Sjacobs 
428*2264Sjacobs 	else
429*2264Sjacobs 	{
430*2264Sjacobs 		*ld = NULL;
431*2264Sjacobs 
432*2264Sjacobs 		/* if host was not given then bind to local host */
433*2264Sjacobs 
434*2264Sjacobs 		if (cred->host != NULL)
435*2264Sjacobs 		{
436*2264Sjacobs 			(void) strlcpy(hostname, cred->host, sizeof (hostname));
437*2264Sjacobs 		}
438*2264Sjacobs 		else
439*2264Sjacobs 		{
440*2264Sjacobs 			(void) sysinfo(SI_HOSTNAME,
441*2264Sjacobs 					hostname, sizeof (hostname));
442*2264Sjacobs 		}
443*2264Sjacobs 
444*2264Sjacobs 		/* initialise the connection to the ldap server */
445*2264Sjacobs 
446*2264Sjacobs 		if (cred->port != 0)
447*2264Sjacobs 		{
448*2264Sjacobs 			ldapPort = cred->port;
449*2264Sjacobs 		}
450*2264Sjacobs 		*ld = ldap_init(hostname, ldapPort);
451*2264Sjacobs 		if (*ld == NULL)
452*2264Sjacobs 		{
453*2264Sjacobs 			/* connection setup failed */
454*2264Sjacobs 			result = NSL_ERR_CONNECT;
455*2264Sjacobs #ifdef DEBUG
456*2264Sjacobs (void) perror("ldap_init");
457*2264Sjacobs #endif
458*2264Sjacobs 		}
459*2264Sjacobs 		else
460*2264Sjacobs 		{
461*2264Sjacobs 			/* set ldap options */
462*2264Sjacobs 
463*2264Sjacobs 			(void) ldap_set_option(*ld, LDAP_OPT_DEREF,
464*2264Sjacobs 						&derefOption);
465*2264Sjacobs 			(void) ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION,
466*2264Sjacobs 						&protoVersion);
467*2264Sjacobs 			(void) ldap_set_option(*ld, LDAP_OPT_REFERRALS,
468*2264Sjacobs 						&referrals);
469*2264Sjacobs 
470*2264Sjacobs 			/* bind to the user DN in the directory */
471*2264Sjacobs 
472*2264Sjacobs 			/* cred->passwdType is currently not supported */
473*2264Sjacobs 
474*2264Sjacobs 			lresult = ldap_simple_bind_s(*ld,
475*2264Sjacobs 						cred->binddn, cred->passwd);
476*2264Sjacobs 
477*2264Sjacobs 			/*
478*2264Sjacobs 			 * before doing anything else, set up the function to
479*2264Sjacobs 			 * call to get authentication details if the
480*2264Sjacobs 			 * ldap update function calls (eg. ldap_add_s()) get a
481*2264Sjacobs 			 * "referral" (to another ldap server) from the
482*2264Sjacobs 			 * original ldap server, eg. if we are trying to do
483*2264Sjacobs 			 * a update on a LDAP replica server.
484*2264Sjacobs 			 */
485*2264Sjacobs 			(void) _manageReferralCredentials(*ld,
486*2264Sjacobs 					&(cred->binddn), &(cred->passwd),
487*2264Sjacobs 					&tmpMethod, -1);
488*2264Sjacobs 			ldap_set_rebind_proc(*ld,
489*2264Sjacobs 			    (LDAP_REBINDPROC_CALLBACK *)
490*2264Sjacobs 				_manageReferralCredentials, NULL);
491*2264Sjacobs 
492*2264Sjacobs 			if (lresult != LDAP_SUCCESS)
493*2264Sjacobs 			{
494*2264Sjacobs 				result = NSL_ERR_BIND;
495*2264Sjacobs 				*ld = NULL;
496*2264Sjacobs #ifdef DEBUG
497*2264Sjacobs (void) ldap_perror(*ld, "ldap_simple_bind_s");
498*2264Sjacobs #endif
499*2264Sjacobs 			}
500*2264Sjacobs 		}
501*2264Sjacobs 	}
502*2264Sjacobs 
503*2264Sjacobs 	return (result);
504*2264Sjacobs } /* _connectToLDAP */
505*2264Sjacobs 
506*2264Sjacobs 
507*2264Sjacobs 
508*2264Sjacobs 
509*2264Sjacobs 
510*2264Sjacobs /*
511*2264Sjacobs  * *****************************************************************************
512*2264Sjacobs  *
513*2264Sjacobs  * Function:    _constructPrinterDN()
514*2264Sjacobs  *
515*2264Sjacobs  * Description: Construct the DN for the printer object from its name and NS
516*2264Sjacobs  *              domain DN. If the printer-uri is given in the attrList then
517*2264Sjacobs  *              that is used instead of the printerName.
518*2264Sjacobs  *
519*2264Sjacobs  * Parameters:
520*2264Sjacobs  * Input:       uchar_t *printerName
521*2264Sjacobs  *              uchar_t *domainDN
522*2264Sjacobs  *              char **attrList - this list is searched for printer-uri
523*2264Sjacobs  * Output:      None
524*2264Sjacobs  *
525*2264Sjacobs  * Returns:     uchar_t* - pointer to the DN, this memory is malloced so
526*2264Sjacobs  *                         must be freed using free() when finished with.
527*2264Sjacobs  *
528*2264Sjacobs  * *****************************************************************************
529*2264Sjacobs  */
530*2264Sjacobs 
531*2264Sjacobs static uchar_t *
532*2264Sjacobs _constructPrinterDN(uchar_t *printerName, uchar_t *domainDN, char **attrList)
533*2264Sjacobs 
534*2264Sjacobs {
535*2264Sjacobs 	uchar_t *dn = NULL;
536*2264Sjacobs 	uchar_t *uri = NULL;
537*2264Sjacobs 	char **p = NULL;
538*2264Sjacobs 	int len = 0;
539*2264Sjacobs 
540*2264Sjacobs 	/* ------- */
541*2264Sjacobs 
542*2264Sjacobs 	/* first search for printer-uri in the attribute list */
543*2264Sjacobs 
544*2264Sjacobs 	for (p = attrList; (p != NULL) && (*p != NULL) && (uri == NULL); p++)
545*2264Sjacobs 	{
546*2264Sjacobs 		/* get length of this key word */
547*2264Sjacobs 
548*2264Sjacobs 		for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
549*2264Sjacobs 
550*2264Sjacobs 		if ((strncasecmp(*p, ATTR_URI, len) == 0) &&
551*2264Sjacobs 		    (strlen(*p) > len+1))
552*2264Sjacobs 		{
553*2264Sjacobs 			uri = (uchar_t *)&((*p)[len+1]);
554*2264Sjacobs 		}
555*2264Sjacobs 	}
556*2264Sjacobs 
557*2264Sjacobs 
558*2264Sjacobs 	if (domainDN != NULL) {
559*2264Sjacobs 		size_t size;
560*2264Sjacobs 
561*2264Sjacobs 		/* malloc memory for the DN and then construct it */
562*2264Sjacobs 
563*2264Sjacobs 		if ((uri == NULL) && (printerName != NULL))
564*2264Sjacobs 		{
565*2264Sjacobs 			/* use the printerName for the RDN */
566*2264Sjacobs 
567*2264Sjacobs 			size = strlen(ATTR_URI) +
568*2264Sjacobs 			    strlen((char *)printerName) +
569*2264Sjacobs 			    strlen((char *)domainDN) +
570*2264Sjacobs 			    strlen(PCONTAINER) +
571*2264Sjacobs 			    10; /* plus a few extra */
572*2264Sjacobs 
573*2264Sjacobs 			if ((dn = malloc(size)) != NULL)
574*2264Sjacobs 				(void) snprintf((char *)dn, size, "%s=%s,%s,%s",
575*2264Sjacobs 				ATTR_URI, printerName, PCONTAINER, domainDN);
576*2264Sjacobs 		}
577*2264Sjacobs 		else
578*2264Sjacobs 		if (uri != NULL)
579*2264Sjacobs 		{
580*2264Sjacobs 			/* use the URI for the RDN */
581*2264Sjacobs 
582*2264Sjacobs 			size = strlen(ATTR_URI) +
583*2264Sjacobs 			    strlen((char *)uri) +
584*2264Sjacobs 			    strlen((char *)domainDN) +
585*2264Sjacobs 			    strlen(PCONTAINER) +
586*2264Sjacobs 			    10; /* plus a few extra */
587*2264Sjacobs 
588*2264Sjacobs 			if ((dn = malloc(size)) != NULL)
589*2264Sjacobs 				(void) snprintf((char *)dn, size, "%s=%s,%s,%s",
590*2264Sjacobs 				ATTR_URI, uri, PCONTAINER, domainDN);
591*2264Sjacobs 		}
592*2264Sjacobs 
593*2264Sjacobs 		/*
594*2264Sjacobs 		 * else
595*2264Sjacobs 		 * {
596*2264Sjacobs 		 *    printName not given so return null
597*2264Sjacobs 		 * }
598*2264Sjacobs 		 */
599*2264Sjacobs 
600*2264Sjacobs 	}
601*2264Sjacobs 
602*2264Sjacobs 	return (dn);	/* caller must free this memory */
603*2264Sjacobs } /* _constructPrinterDN */
604*2264Sjacobs 
605*2264Sjacobs 
606*2264Sjacobs 
607*2264Sjacobs /*
608*2264Sjacobs  * *****************************************************************************
609*2264Sjacobs  *
610*2264Sjacobs  * Function:    _checkPrinterExists()
611*2264Sjacobs  *
612*2264Sjacobs  * Description: Check that the printer object for the printerName exists in the
613*2264Sjacobs  *              directory DIT and then extract the object's DN
614*2264Sjacobs  *              The function uses an exiting ldap connection and does a
615*2264Sjacobs  *              search for the printerName in the supplied domain DN.
616*2264Sjacobs  *
617*2264Sjacobs  * Parameters:
618*2264Sjacobs  * Input:       LDAP *ld             - existing ldap connection descriptor
619*2264Sjacobs  *              uchar_t *printerName - printer name
620*2264Sjacobs  *              uchar_t *domainDN    - DN of domain to search in
621*2264Sjacobs  * Output:      uchar_t **printerDN  - DN of the printer - the caller should
622*2264Sjacobs  *                                     free this memory using free()
623*2264Sjacobs  *
624*2264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists
625*2264Sjacobs  *
626*2264Sjacobs  * *****************************************************************************
627*2264Sjacobs  */
628*2264Sjacobs 
629*2264Sjacobs static NSL_RESULT
630*2264Sjacobs _checkPrinterExists(LDAP *ld, uchar_t *printerName, uchar_t *domainDN,
631*2264Sjacobs 			uchar_t **printerDN)
632*2264Sjacobs 
633*2264Sjacobs {
634*2264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
635*2264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
636*2264Sjacobs 	LDAPMessage *ldapMsg = NULL;
637*2264Sjacobs 	char *requiredAttrs[2] = { ATTR_PNAME, NULL };
638*2264Sjacobs 	LDAPMessage *ldapEntry = NULL;
639*2264Sjacobs 	uchar_t *filter = NULL;
640*2264Sjacobs 	uchar_t *baseDN = NULL;
641*2264Sjacobs 
642*2264Sjacobs 	/* ---------- */
643*2264Sjacobs 
644*2264Sjacobs 	if ((printerName != NULL) && (domainDN != NULL) && (printerDN != NULL))
645*2264Sjacobs 	{
646*2264Sjacobs 		size_t size;
647*2264Sjacobs 
648*2264Sjacobs 		if (printerDN != NULL)
649*2264Sjacobs 		{
650*2264Sjacobs 			*printerDN = NULL;
651*2264Sjacobs 		}
652*2264Sjacobs 
653*2264Sjacobs 		/* search for this Printer in the directory */
654*2264Sjacobs 
655*2264Sjacobs 		size = (3 + strlen((char *)printerName) + strlen(ATTR_PNAME) +
656*2264Sjacobs 			2);
657*2264Sjacobs 
658*2264Sjacobs 		if ((filter = malloc(size)) != NULL)
659*2264Sjacobs 			(void) snprintf((char *)filter, size, "(%s=%s)",
660*2264Sjacobs 			    ATTR_PNAME, (char *)printerName);
661*2264Sjacobs 
662*2264Sjacobs 		size = (strlen((char *)domainDN) + strlen(PCONTAINER) + 5);
663*2264Sjacobs 
664*2264Sjacobs 		if ((baseDN = malloc(size)) != NULL)
665*2264Sjacobs 			(void) snprintf((char *)baseDN, size, "%s,%s",
666*2264Sjacobs 			    PCONTAINER, (char *)domainDN);
667*2264Sjacobs 
668*2264Sjacobs 		sresult = ldap_search_s(ld, (char *)baseDN, LDAP_SCOPE_SUBTREE,
669*2264Sjacobs 				(char *)filter, requiredAttrs, 0, &ldapMsg);
670*2264Sjacobs 		if (sresult == LDAP_SUCCESS)
671*2264Sjacobs 		{
672*2264Sjacobs 			/* check that the object exists and extract its DN */
673*2264Sjacobs 
674*2264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
675*2264Sjacobs 			if (ldapEntry != NULL)
676*2264Sjacobs 			{
677*2264Sjacobs 				/* object found - there should only be one */
678*2264Sjacobs 				result = NSL_OK;
679*2264Sjacobs 
680*2264Sjacobs 				if (printerDN != NULL)
681*2264Sjacobs 				{
682*2264Sjacobs 					*printerDN = (uchar_t *)
683*2264Sjacobs 						ldap_get_dn(ld, ldapEntry);
684*2264Sjacobs 				}
685*2264Sjacobs 			}
686*2264Sjacobs 
687*2264Sjacobs 			(void) ldap_msgfree(ldapMsg);
688*2264Sjacobs 		}
689*2264Sjacobs 	}
690*2264Sjacobs 
691*2264Sjacobs 	else
692*2264Sjacobs 	{
693*2264Sjacobs 		result = NSL_ERR_INTERNAL;
694*2264Sjacobs 	}
695*2264Sjacobs 
696*2264Sjacobs 	return (result);
697*2264Sjacobs } /* _checkPrinterExists */
698*2264Sjacobs 
699*2264Sjacobs 
700*2264Sjacobs 
701*2264Sjacobs 
702*2264Sjacobs /*
703*2264Sjacobs  * *****************************************************************************
704*2264Sjacobs  *
705*2264Sjacobs  * Function:    _checkPrinterDNExists()
706*2264Sjacobs  *
707*2264Sjacobs  * Description: Check that the printer object for the DN exists in the
708*2264Sjacobs  *              directory DIT.
709*2264Sjacobs  *              The function uses an exiting ldap connection and does a
710*2264Sjacobs  *              search for the DN supplied.
711*2264Sjacobs  *
712*2264Sjacobs  * Parameters:  LDAP *ld       - existing ldap connection descriptor
713*2264Sjacobs  *              char *objectDN - DN to search for
714*2264Sjacobs  *
715*2264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists
716*2264Sjacobs  *
717*2264Sjacobs  * *****************************************************************************
718*2264Sjacobs  */
719*2264Sjacobs 
720*2264Sjacobs static NSL_RESULT
721*2264Sjacobs _checkPrinterDNExists(LDAP *ld, uchar_t *objectDN)
722*2264Sjacobs 
723*2264Sjacobs {
724*2264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
725*2264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
726*2264Sjacobs 	LDAPMessage *ldapMsg;
727*2264Sjacobs 	char *requiredAttrs[2] = { ATTR_PNAME, NULL };
728*2264Sjacobs 	LDAPMessage *ldapEntry;
729*2264Sjacobs 
730*2264Sjacobs 	/* ---------- */
731*2264Sjacobs 
732*2264Sjacobs 	if ((ld != NULL) && (objectDN != NULL))
733*2264Sjacobs 	{
734*2264Sjacobs 		/* search for this Printer in the directory */
735*2264Sjacobs 
736*2264Sjacobs 		sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE,
737*2264Sjacobs 				"(objectclass=*)", requiredAttrs, 0, &ldapMsg);
738*2264Sjacobs 		if (sresult == LDAP_SUCCESS)
739*2264Sjacobs 		{
740*2264Sjacobs 			/* check that the object exists */
741*2264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
742*2264Sjacobs 			if (ldapEntry != NULL)
743*2264Sjacobs 			{
744*2264Sjacobs 				/* object found */
745*2264Sjacobs 				result = NSL_OK;
746*2264Sjacobs 			}
747*2264Sjacobs 
748*2264Sjacobs 			(void) ldap_msgfree(ldapMsg);
749*2264Sjacobs 		}
750*2264Sjacobs 	}
751*2264Sjacobs 
752*2264Sjacobs 	else
753*2264Sjacobs 	{
754*2264Sjacobs 		result = NSL_ERR_INTERNAL;
755*2264Sjacobs 	}
756*2264Sjacobs 
757*2264Sjacobs 	return (result);
758*2264Sjacobs } /* _checkPrinterDNExists */
759*2264Sjacobs 
760*2264Sjacobs 
761*2264Sjacobs 
762*2264Sjacobs 
763*2264Sjacobs 
764*2264Sjacobs /*
765*2264Sjacobs  * *****************************************************************************
766*2264Sjacobs  *
767*2264Sjacobs  * Function:    _checkSunPrinter()
768*2264Sjacobs  *
769*2264Sjacobs  * Description: Check that the printer object for the printerDN is a sunPrinter
770*2264Sjacobs  *              ie. it has the required objectclass attribute value.
771*2264Sjacobs  *
772*2264Sjacobs  * Parameters:
773*2264Sjacobs  * Input:       LDAP *ld            - existing ldap connection descriptor
774*2264Sjacobs  * Output:      uchar_t *printerDN  - DN of the printer
775*2264Sjacobs  *
776*2264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists and is a sunPrinter
777*2264Sjacobs  *
778*2264Sjacobs  * *****************************************************************************
779*2264Sjacobs  */
780*2264Sjacobs 
781*2264Sjacobs static NSL_RESULT
782*2264Sjacobs _checkSunPrinter(LDAP *ld, uchar_t *printerDN)
783*2264Sjacobs 
784*2264Sjacobs {
785*2264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
786*2264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
787*2264Sjacobs 	char *requiredAttrs[2] = { ATTR_PNAME, NULL };
788*2264Sjacobs 	LDAPMessage *ldapMsg = NULL;
789*2264Sjacobs 	LDAPMessage *ldapEntry = NULL;
790*2264Sjacobs 	char *filter = NULL;
791*2264Sjacobs 
792*2264Sjacobs 	/* ---------- */
793*2264Sjacobs 
794*2264Sjacobs 	if ((ld != NULL) && (printerDN != NULL))
795*2264Sjacobs 	{
796*2264Sjacobs 		size_t size;
797*2264Sjacobs 
798*2264Sjacobs 		/* search for this Printer in the directory */
799*2264Sjacobs 
800*2264Sjacobs 		size = (3 + strlen(OCV_SUNPRT) + strlen(ATTR_OCLASS) + 2);
801*2264Sjacobs 		if ((filter = malloc(size)) != NULL)
802*2264Sjacobs 			(void) snprintf(filter, size, "(%s=%s)",
803*2264Sjacobs 					ATTR_OCLASS, OCV_SUNPRT);
804*2264Sjacobs 
805*2264Sjacobs 		sresult = ldap_search_s(ld, (char *)printerDN,
806*2264Sjacobs 						LDAP_SCOPE_SUBTREE, filter,
807*2264Sjacobs 						requiredAttrs, 0, &ldapMsg);
808*2264Sjacobs 		if (sresult == LDAP_SUCCESS)
809*2264Sjacobs 		{
810*2264Sjacobs 			/* check that the printer object exists */
811*2264Sjacobs 
812*2264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
813*2264Sjacobs 			if (ldapEntry != NULL)
814*2264Sjacobs 			{
815*2264Sjacobs 				/* object is a sunPrinter */
816*2264Sjacobs 				result = NSL_OK;
817*2264Sjacobs 			}
818*2264Sjacobs 
819*2264Sjacobs 			(void) ldap_msgfree(ldapMsg);
820*2264Sjacobs 		}
821*2264Sjacobs 	}
822*2264Sjacobs 
823*2264Sjacobs 	else
824*2264Sjacobs 	{
825*2264Sjacobs 		result = NSL_ERR_INTERNAL;
826*2264Sjacobs 	}
827*2264Sjacobs 
828*2264Sjacobs 	return (result);
829*2264Sjacobs } /* _checkSunPrinter */
830*2264Sjacobs 
831*2264Sjacobs 
832*2264Sjacobs 
833*2264Sjacobs 
834*2264Sjacobs 
835*2264Sjacobs /*
836*2264Sjacobs  * *****************************************************************************
837*2264Sjacobs  *
838*2264Sjacobs  * Function:    _addNewPrinterObject()
839*2264Sjacobs  *
840*2264Sjacobs  * Description: For the given printerName add a printer object into the
841*2264Sjacobs  *              LDAP directory NS domain. The object is created with the
842*2264Sjacobs  *              supplied attribute values. Note: if the printer's uri is
843*2264Sjacobs  *              given that is used as the RDN otherwise the printer's
844*2264Sjacobs  *              name is used as the RDN
845*2264Sjacobs  *
846*2264Sjacobs  * Parameters:
847*2264Sjacobs  * Input:       LDAP    *ld        - existing ldap connection descriptor
848*2264Sjacobs  *              uchar_t *printerName - Name of printer to be added
849*2264Sjacobs  *              uchar_t *domainDN    - DN of the domain to add the printer
850*2264Sjacobs  *              char    **attrList - user specified attribute values list
851*2264Sjacobs  * Output:      None
852*2264Sjacobs  *
853*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK  = request actioned okay
854*2264Sjacobs  *                           !NSL_OK = error
855*2264Sjacobs  *
856*2264Sjacobs  * *****************************************************************************
857*2264Sjacobs  */
858*2264Sjacobs 
859*2264Sjacobs static NSL_RESULT
860*2264Sjacobs _addNewPrinterObject(LDAP *ld, uchar_t *printerName,
861*2264Sjacobs 			uchar_t *domainDN, char **attrList)
862*2264Sjacobs 
863*2264Sjacobs {
864*2264Sjacobs 	NSL_RESULT result = NSL_ERR_ADD_FAILED;
865*2264Sjacobs 	int lresult = 0;
866*2264Sjacobs 	uchar_t *printerDN = NULL;
867*2264Sjacobs 	LDAPMod **attrs = NULL;
868*2264Sjacobs 
869*2264Sjacobs 	/* ---------- */
870*2264Sjacobs 
871*2264Sjacobs 	if ((ld != NULL) && (printerName != NULL) && (domainDN != NULL) &&
872*2264Sjacobs 		(attrList != NULL) && (attrList[0] != NULL))
873*2264Sjacobs 	{
874*2264Sjacobs 		result = _checkAttributes(attrList);
875*2264Sjacobs 
876*2264Sjacobs 		if (result == NSL_OK)
877*2264Sjacobs 		{
878*2264Sjacobs 			/*
879*2264Sjacobs 			 * construct a DN for the printer from the
880*2264Sjacobs 			 * printerName and printer-uri if given.
881*2264Sjacobs 			 */
882*2264Sjacobs 			printerDN = _constructPrinterDN(printerName,
883*2264Sjacobs 						domainDN, attrList);
884*2264Sjacobs 			if (printerDN != NULL)
885*2264Sjacobs 			{
886*2264Sjacobs 				/*
887*2264Sjacobs 				 * setup attribute values in an LDAPMod
888*2264Sjacobs 				 * structure and then add the object
889*2264Sjacobs 				 */
890*2264Sjacobs 				result = _constructAddLDAPMod(printerName,
891*2264Sjacobs 							attrList, &attrs);
892*2264Sjacobs 				if (result == NSL_OK)
893*2264Sjacobs 				{
894*2264Sjacobs 					lresult = ldap_add_s(ld,
895*2264Sjacobs 						    (char *)printerDN, attrs);
896*2264Sjacobs 					if (lresult == LDAP_SUCCESS)
897*2264Sjacobs 					{
898*2264Sjacobs 						result = NSL_OK;
899*2264Sjacobs 					}
900*2264Sjacobs 					else
901*2264Sjacobs 					{
902*2264Sjacobs 						result = NSL_ERR_ADD_FAILED;
903*2264Sjacobs #ifdef DEBUG
904*2264Sjacobs (void) ldap_perror(ld, "ldap_add_s");
905*2264Sjacobs #endif
906*2264Sjacobs 					}
907*2264Sjacobs 
908*2264Sjacobs 					(void) ldap_mods_free(attrs, 1);
909*2264Sjacobs 				}
910*2264Sjacobs 				free(printerDN);
911*2264Sjacobs 			}
912*2264Sjacobs 
913*2264Sjacobs 			else
914*2264Sjacobs 			{
915*2264Sjacobs 				result = NSL_ERR_INTERNAL;
916*2264Sjacobs 			}
917*2264Sjacobs 		}
918*2264Sjacobs 	}
919*2264Sjacobs 
920*2264Sjacobs 	else
921*2264Sjacobs 	{
922*2264Sjacobs 		result = NSL_ERR_INTERNAL;
923*2264Sjacobs 	}
924*2264Sjacobs 
925*2264Sjacobs 	return (result);
926*2264Sjacobs } /* _addNewPrinterObject */
927*2264Sjacobs 
928*2264Sjacobs 
929*2264Sjacobs 
930*2264Sjacobs 
931*2264Sjacobs 
932*2264Sjacobs 
933*2264Sjacobs /*
934*2264Sjacobs  * *****************************************************************************
935*2264Sjacobs  *
936*2264Sjacobs  * Function:    _modifyPrinterObject()
937*2264Sjacobs  *
938*2264Sjacobs  * Description: Modify the given LDAP printer object to set the new attributes
939*2264Sjacobs  *              in the attribute list. If the printer's URI (specified in the
940*2264Sjacobs  *              attrList) changes the URI of the object the request is rejected.
941*2264Sjacobs  *
942*2264Sjacobs  * Parameters:
943*2264Sjacobs  * Input:       LDAP    *ld        - existing ldap connection descriptor
944*2264Sjacobs  *              uchar_t *printerDN - DN of printer object to modify
945*2264Sjacobs  *              uchar_t *printerName - Name of printer to be modified
946*2264Sjacobs  *              uchar_t *domainDN    - DN of the domain the printer is in
947*2264Sjacobs  *              char    **attrList - user specified attribute values list
948*2264Sjacobs  * Output:      None
949*2264Sjacobs  *
950*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = object modified okay
951*2264Sjacobs  *
952*2264Sjacobs  * *****************************************************************************
953*2264Sjacobs  */
954*2264Sjacobs 
955*2264Sjacobs static NSL_RESULT
956*2264Sjacobs _modifyPrinterObject(LDAP *ld, uchar_t *printerDN,
957*2264Sjacobs 		uchar_t *printerName, uchar_t *domainDN, char **attrList)
958*2264Sjacobs 
959*2264Sjacobs {
960*2264Sjacobs 	NSL_RESULT result = NSL_ERR_INTERNAL;
961*2264Sjacobs 	int lresult = 0;
962*2264Sjacobs 	int sunPrinter = 0;
963*2264Sjacobs 	uchar_t *uriDN = NULL;
964*2264Sjacobs 	LDAPMod **attrs = NULL;
965*2264Sjacobs 	char **kvpList = NULL;
966*2264Sjacobs 
967*2264Sjacobs 	/* ---------- */
968*2264Sjacobs 
969*2264Sjacobs 	if ((ld != NULL) && (printerDN != NULL) && (printerName != NULL) &&
970*2264Sjacobs 	    (domainDN != NULL) && (attrList != NULL) && (attrList[0] != NULL))
971*2264Sjacobs 	{
972*2264Sjacobs 		result = _checkAttributes(attrList);
973*2264Sjacobs 
974*2264Sjacobs 		if (result == NSL_OK)
975*2264Sjacobs 		{
976*2264Sjacobs 			/*
977*2264Sjacobs 			 * The user may have requested that the printer object
978*2264Sjacobs 			 * be given a new URI RDN, so construct a DN for the
979*2264Sjacobs 			 * printer from the printerName or the printer-uri (if
980*2264Sjacobs 			 * given).
981*2264Sjacobs 			 */
982*2264Sjacobs 			uriDN = _constructPrinterDN(NULL, domainDN, attrList);
983*2264Sjacobs 
984*2264Sjacobs 			/*
985*2264Sjacobs 			 * compare the 2 DNs to see if the URI has changed,
986*2264Sjacobs 			 * if uriDN is null then the DN hasn't changed
987*2264Sjacobs 			 */
988*2264Sjacobs 			if ((uriDN == NULL) || ((uriDN != NULL) &&
989*2264Sjacobs 			    (_compareURIinDNs(printerDN, uriDN) == NSL_OK)))
990*2264Sjacobs 			{
991*2264Sjacobs 				/*
992*2264Sjacobs 				 * setup the modify object LDAPMod
993*2264Sjacobs 				 * structure and then do the modify
994*2264Sjacobs 				 */
995*2264Sjacobs 
996*2264Sjacobs 				if (_checkSunPrinter(ld, printerDN) == NSL_OK)
997*2264Sjacobs 				{
998*2264Sjacobs 					sunPrinter = 1;
999*2264Sjacobs 				}
1000*2264Sjacobs 
1001*2264Sjacobs 				(void) _getCurrentKVPValues(ld,
1002*2264Sjacobs 							printerDN, &kvpList);
1003*2264Sjacobs 
1004*2264Sjacobs 				result = _constructModLDAPMod(printerName,
1005*2264Sjacobs 							sunPrinter, attrList,
1006*2264Sjacobs 							&kvpList, &attrs);
1007*2264Sjacobs 				_freeList(&kvpList);
1008*2264Sjacobs 
1009*2264Sjacobs 				if ((result == NSL_OK) && (attrs != NULL))
1010*2264Sjacobs 				{
1011*2264Sjacobs 					lresult = ldap_modify_s(
1012*2264Sjacobs 						ld, (char *)printerDN, attrs);
1013*2264Sjacobs 					if (lresult == LDAP_SUCCESS)
1014*2264Sjacobs 					{
1015*2264Sjacobs 						result = NSL_OK;
1016*2264Sjacobs 					}
1017*2264Sjacobs 					else
1018*2264Sjacobs 					{
1019*2264Sjacobs 						result = NSL_ERR_MOD_FAILED;
1020*2264Sjacobs #ifdef DEBUG
1021*2264Sjacobs (void) ldap_perror(ld, "ldap_modify_s");
1022*2264Sjacobs #endif
1023*2264Sjacobs 					}
1024*2264Sjacobs 
1025*2264Sjacobs 					(void) ldap_mods_free(attrs, 1);
1026*2264Sjacobs 				}
1027*2264Sjacobs 			}
1028*2264Sjacobs 			else
1029*2264Sjacobs 			{
1030*2264Sjacobs 				/*
1031*2264Sjacobs 				 * printer-uri name change has been requested
1032*2264Sjacobs 				 * this is NOT allowed as it requires that
1033*2264Sjacobs 				 * a new printer object is created
1034*2264Sjacobs 				 */
1035*2264Sjacobs 				result = NSL_ERR_RENAME;  /* NOT ALLOWED */
1036*2264Sjacobs 			}
1037*2264Sjacobs 
1038*2264Sjacobs 			if (uriDN != NULL)
1039*2264Sjacobs 			{
1040*2264Sjacobs 				free(uriDN);
1041*2264Sjacobs 			}
1042*2264Sjacobs 		}
1043*2264Sjacobs 	}
1044*2264Sjacobs 
1045*2264Sjacobs 	return (result);
1046*2264Sjacobs } /* _modifyPrinterObject */
1047*2264Sjacobs 
1048*2264Sjacobs 
1049*2264Sjacobs 
1050*2264Sjacobs 
1051*2264Sjacobs /*
1052*2264Sjacobs  * *****************************************************************************
1053*2264Sjacobs  *
1054*2264Sjacobs  * Function:    _checkAttributes()
1055*2264Sjacobs  *
1056*2264Sjacobs  * Description: Check that the given attribute lists does not contain any
1057*2264Sjacobs  *              key words that are not allowed.
1058*2264Sjacobs  *
1059*2264Sjacobs  * Parameters:
1060*2264Sjacobs  * Input:       char **list - attribute list to check
1061*2264Sjacobs  * Output:      None
1062*2264Sjacobs  *
1063*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = checked okay
1064*2264Sjacobs  *
1065*2264Sjacobs  * *****************************************************************************
1066*2264Sjacobs  */
1067*2264Sjacobs 
1068*2264Sjacobs static NSL_RESULT
1069*2264Sjacobs _checkAttributes(char **list)
1070*2264Sjacobs 
1071*2264Sjacobs {
1072*2264Sjacobs 	NSL_RESULT result = NSL_OK;
1073*2264Sjacobs 	int len = 0;
1074*2264Sjacobs 	char *attr = NULL;
1075*2264Sjacobs 	char **p = NULL;
1076*2264Sjacobs 
1077*2264Sjacobs 	/* ------ */
1078*2264Sjacobs 
1079*2264Sjacobs 	for (p = list; (p != NULL) && (*p != NULL) && (result == NSL_OK); p++)
1080*2264Sjacobs 	{
1081*2264Sjacobs 		/* get length of this key word */
1082*2264Sjacobs 
1083*2264Sjacobs 		for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
1084*2264Sjacobs 
1085*2264Sjacobs 		/* check if the key word is allowed */
1086*2264Sjacobs 
1087*2264Sjacobs 		if (strncasecmp(*p, ATTR_KVP, len) == 0)
1088*2264Sjacobs 		{
1089*2264Sjacobs 			/* not supported through this interface */
1090*2264Sjacobs 			result = NSL_ERR_KVP;
1091*2264Sjacobs 		}
1092*2264Sjacobs 		else
1093*2264Sjacobs 		if (strncasecmp(*p, ATTR_BSDADDR, len) == 0)
1094*2264Sjacobs 		{
1095*2264Sjacobs 			/* not supported through this interface */
1096*2264Sjacobs 			result = NSL_ERR_BSDADDR;
1097*2264Sjacobs 		}
1098*2264Sjacobs 		else
1099*2264Sjacobs 		if (strncasecmp(*p, ATTR_PNAME, len) == 0)
1100*2264Sjacobs 		{
1101*2264Sjacobs 			/* not supported through this interface */
1102*2264Sjacobs 			result = NSL_ERR_PNAME;
1103*2264Sjacobs 		}
1104*2264Sjacobs 		else
1105*2264Sjacobs 		{
1106*2264Sjacobs 			/* check for any others */
1107*2264Sjacobs 
1108*2264Sjacobs 			attr = strdup(*p);
1109*2264Sjacobs 			attr[len] = '\0'; /* terminate the key */
1110*2264Sjacobs 
1111*2264Sjacobs 			if (_attrInList(attr, nsl_attr_notAllowed))
1112*2264Sjacobs 			{
1113*2264Sjacobs 				result = NSL_ERR_NOTALLOWED;
1114*2264Sjacobs 			}
1115*2264Sjacobs 		}
1116*2264Sjacobs 
1117*2264Sjacobs 	}
1118*2264Sjacobs 
1119*2264Sjacobs 	return (result);
1120*2264Sjacobs } /* _checkAttributes */
1121*2264Sjacobs 
1122*2264Sjacobs 
1123*2264Sjacobs 
1124*2264Sjacobs 
1125*2264Sjacobs /*
1126*2264Sjacobs  * *****************************************************************************
1127*2264Sjacobs  *
1128*2264Sjacobs  * Function:    _addLDAPmodValue()
1129*2264Sjacobs  *
1130*2264Sjacobs  * Description: Add the given attribute and its value to the LDAPMod array.
1131*2264Sjacobs  *              If this is the first entry in the array then create it.
1132*2264Sjacobs  *
1133*2264Sjacobs  * Parameters:
1134*2264Sjacobs  * Input:       LDAPMod ***attrs  - array to update
1135*2264Sjacobs  *              char *type        - attribute to add into array
1136*2264Sjacobs  *              char *value       - attribute value
1137*2264Sjacobs  * Output:      None
1138*2264Sjacobs  *
1139*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = added okay
1140*2264Sjacobs  *
1141*2264Sjacobs  * *****************************************************************************
1142*2264Sjacobs  */
1143*2264Sjacobs 
1144*2264Sjacobs static NSL_RESULT
1145*2264Sjacobs _addLDAPmodValue(LDAPMod ***attrs, char *type, char *value)
1146*2264Sjacobs 
1147*2264Sjacobs {
1148*2264Sjacobs 	int i = 0;
1149*2264Sjacobs 	int j = 0;
1150*2264Sjacobs 	NSL_RESULT result = NSL_OK;
1151*2264Sjacobs 
1152*2264Sjacobs 	/* ---------- */
1153*2264Sjacobs 
1154*2264Sjacobs 	if ((attrs != NULL) && (type != NULL) && (value != NULL))
1155*2264Sjacobs 	{
1156*2264Sjacobs #ifdef DEBUG
1157*2264Sjacobs printf("_addLDAPmodValue() type='%s', value='%s'\n", type, value);
1158*2264Sjacobs #endif
1159*2264Sjacobs 		/* search the existing LDAPMod array for the attribute */
1160*2264Sjacobs 
1161*2264Sjacobs 		for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++)
1162*2264Sjacobs 		{
1163*2264Sjacobs 			if (strcasecmp((*attrs)[i]->mod_type, type) == 0)
1164*2264Sjacobs 			{
1165*2264Sjacobs 				break;
1166*2264Sjacobs 			}
1167*2264Sjacobs 		}
1168*2264Sjacobs 
1169*2264Sjacobs 		if (*attrs == NULL)
1170*2264Sjacobs 		{
1171*2264Sjacobs 			/* array empty so create it */
1172*2264Sjacobs 
1173*2264Sjacobs 			*attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *));
1174*2264Sjacobs 			if (*attrs != NULL)
1175*2264Sjacobs 			{
1176*2264Sjacobs 				i = 0;
1177*2264Sjacobs 			}
1178*2264Sjacobs 			else
1179*2264Sjacobs 			{
1180*2264Sjacobs 				result = NSL_ERR_MEMORY;
1181*2264Sjacobs 			}
1182*2264Sjacobs 
1183*2264Sjacobs 		}
1184*2264Sjacobs 		else
1185*2264Sjacobs 		if ((*attrs)[i] == NULL)
1186*2264Sjacobs 		{
1187*2264Sjacobs 			*attrs = (LDAPMod **)
1188*2264Sjacobs 				realloc(*attrs, (i+2) * sizeof (LDAPMod *));
1189*2264Sjacobs 			if (*attrs == NULL)
1190*2264Sjacobs 			{
1191*2264Sjacobs 				result = NSL_ERR_MEMORY;
1192*2264Sjacobs 			}
1193*2264Sjacobs 		}
1194*2264Sjacobs 	}
1195*2264Sjacobs 	else
1196*2264Sjacobs 	{
1197*2264Sjacobs 		result = NSL_ERR_INTERNAL;
1198*2264Sjacobs 	}
1199*2264Sjacobs 
1200*2264Sjacobs 	if (result == NSL_OK)
1201*2264Sjacobs 	{
1202*2264Sjacobs 		if ((*attrs)[i] == NULL)
1203*2264Sjacobs 		{
1204*2264Sjacobs 			/* We've got a new slot. Create the new mod. */
1205*2264Sjacobs 
1206*2264Sjacobs 			(*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod));
1207*2264Sjacobs 			if ((*attrs)[i] != NULL)
1208*2264Sjacobs 			{
1209*2264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_ADD;
1210*2264Sjacobs 				(*attrs)[i]->mod_type = strdup(type);
1211*2264Sjacobs 				(*attrs)[i]->mod_values = (char **)
1212*2264Sjacobs 						malloc(2 * sizeof (char *));
1213*2264Sjacobs 				if ((*attrs)[i]->mod_values  != NULL)
1214*2264Sjacobs 				{
1215*2264Sjacobs 					(*attrs)[i]->mod_values[0] =
1216*2264Sjacobs 								strdup(value);
1217*2264Sjacobs 					(*attrs)[i]->mod_values[1] = NULL;
1218*2264Sjacobs 					(*attrs)[i+1] = NULL;
1219*2264Sjacobs 				}
1220*2264Sjacobs 				else
1221*2264Sjacobs 				{
1222*2264Sjacobs 					result = NSL_ERR_MEMORY;
1223*2264Sjacobs 				}
1224*2264Sjacobs 			}
1225*2264Sjacobs 			else
1226*2264Sjacobs 			{
1227*2264Sjacobs 				result = NSL_ERR_MEMORY;
1228*2264Sjacobs 			}
1229*2264Sjacobs 		}
1230*2264Sjacobs 
1231*2264Sjacobs 		else
1232*2264Sjacobs 		{
1233*2264Sjacobs 			/* Found an existing entry so add value to it */
1234*2264Sjacobs 
1235*2264Sjacobs 			for (j = 0; (*attrs)[i]->mod_values[j] != NULL; j++);
1236*2264Sjacobs 
1237*2264Sjacobs 			(*attrs)[i]->mod_values =
1238*2264Sjacobs 				(char **)realloc((*attrs)[i]->mod_values,
1239*2264Sjacobs 						(j + 2) * sizeof (char *));
1240*2264Sjacobs 			if ((*attrs)[i]->mod_values != NULL)
1241*2264Sjacobs 			{
1242*2264Sjacobs 				(*attrs)[i]->mod_values[j] = strdup(value);
1243*2264Sjacobs 				(*attrs)[i]->mod_values[j+1] = NULL;
1244*2264Sjacobs 			}
1245*2264Sjacobs 			else
1246*2264Sjacobs 			{
1247*2264Sjacobs 				result = NSL_ERR_MEMORY;
1248*2264Sjacobs 			}
1249*2264Sjacobs 		}
1250*2264Sjacobs 	}
1251*2264Sjacobs 
1252*2264Sjacobs 	return (result);
1253*2264Sjacobs } /* _addLDAPmodValue */
1254*2264Sjacobs 
1255*2264Sjacobs 
1256*2264Sjacobs 
1257*2264Sjacobs 
1258*2264Sjacobs /*
1259*2264Sjacobs  * *****************************************************************************
1260*2264Sjacobs  *
1261*2264Sjacobs  * Function:    _modLDAPmodValue()
1262*2264Sjacobs  *
1263*2264Sjacobs  * Description: Add the given attribute modify operation and its value into
1264*2264Sjacobs  *              the LDAPMod array. This will either be a "replace" or a
1265*2264Sjacobs  *              "delete"; value = null implies a "delete".
1266*2264Sjacobs  *              If this is the first entry in the array then create it.
1267*2264Sjacobs  *
1268*2264Sjacobs  * Parameters:
1269*2264Sjacobs  * Input:       LDAPMod ***attrs  - array to update
1270*2264Sjacobs  *              char *type        - attribute to modify
1271*2264Sjacobs  *              char *value       - attribute value, null implies "delete"
1272*2264Sjacobs  * Output:      None
1273*2264Sjacobs  *
1274*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = added okay
1275*2264Sjacobs  *
1276*2264Sjacobs  * *****************************************************************************
1277*2264Sjacobs  */
1278*2264Sjacobs 
1279*2264Sjacobs static NSL_RESULT
1280*2264Sjacobs _modLDAPmodValue(LDAPMod ***attrs, char *type, char *value)
1281*2264Sjacobs 
1282*2264Sjacobs {
1283*2264Sjacobs 	int i = 0;
1284*2264Sjacobs 	int j = 0;
1285*2264Sjacobs 	NSL_RESULT result = NSL_OK;
1286*2264Sjacobs 
1287*2264Sjacobs 	/* ---------- */
1288*2264Sjacobs 
1289*2264Sjacobs 	if ((attrs != NULL) && (type != NULL))
1290*2264Sjacobs 	{
1291*2264Sjacobs #ifdef DEBUG
1292*2264Sjacobs if (value != NULL)
1293*2264Sjacobs printf("_modLDAPmodValue() REPLACE type='%s', value='%s'\n", type, value);
1294*2264Sjacobs else
1295*2264Sjacobs printf("_modLDAPmodValue() DELETE type='%s'\n", type);
1296*2264Sjacobs #endif
1297*2264Sjacobs 		/* search the existing LDAPMod array for the attribute */
1298*2264Sjacobs 
1299*2264Sjacobs 		for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++)
1300*2264Sjacobs 		{
1301*2264Sjacobs 			if (strcasecmp((*attrs)[i]->mod_type, type) == 0)
1302*2264Sjacobs 			{
1303*2264Sjacobs 				break;
1304*2264Sjacobs 			}
1305*2264Sjacobs 		}
1306*2264Sjacobs 
1307*2264Sjacobs 		if (*attrs == NULL)
1308*2264Sjacobs 		{
1309*2264Sjacobs 			/* array empty so create it */
1310*2264Sjacobs 
1311*2264Sjacobs 			*attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *));
1312*2264Sjacobs 			if (*attrs != NULL)
1313*2264Sjacobs 			{
1314*2264Sjacobs 				i = 0;
1315*2264Sjacobs 			}
1316*2264Sjacobs 			else
1317*2264Sjacobs 			{
1318*2264Sjacobs 				result = NSL_ERR_MEMORY;
1319*2264Sjacobs 			}
1320*2264Sjacobs 
1321*2264Sjacobs 		}
1322*2264Sjacobs 		else
1323*2264Sjacobs 		if ((*attrs)[i] == NULL)
1324*2264Sjacobs 		{
1325*2264Sjacobs 			/* attribute not found in array so add slot for it */
1326*2264Sjacobs 
1327*2264Sjacobs 			*attrs = (LDAPMod **)
1328*2264Sjacobs 				realloc(*attrs, (i+2) * sizeof (LDAPMod *));
1329*2264Sjacobs 			if (*attrs == NULL)
1330*2264Sjacobs 			{
1331*2264Sjacobs 				result = NSL_ERR_MEMORY;
1332*2264Sjacobs 			}
1333*2264Sjacobs 		}
1334*2264Sjacobs 	}
1335*2264Sjacobs 	else
1336*2264Sjacobs 	{
1337*2264Sjacobs 		result = NSL_ERR_INTERNAL;
1338*2264Sjacobs 	}
1339*2264Sjacobs 
1340*2264Sjacobs 	if (result == NSL_OK)
1341*2264Sjacobs 	{
1342*2264Sjacobs 		if ((*attrs)[i] == NULL)
1343*2264Sjacobs 		{
1344*2264Sjacobs 			/* We've got a new slot. Create the new mod entry */
1345*2264Sjacobs 
1346*2264Sjacobs 			(*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod));
1347*2264Sjacobs 			if (((*attrs)[i] != NULL) && (value != NULL))
1348*2264Sjacobs 			{
1349*2264Sjacobs 				/* Do an attribute replace */
1350*2264Sjacobs 
1351*2264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_REPLACE;
1352*2264Sjacobs 				(*attrs)[i]->mod_type = strdup(type);
1353*2264Sjacobs 				(*attrs)[i]->mod_values = (char **)
1354*2264Sjacobs 						malloc(2 * sizeof (char *));
1355*2264Sjacobs 				if ((*attrs)[i]->mod_values  != NULL)
1356*2264Sjacobs 				{
1357*2264Sjacobs 					(*attrs)[i]->mod_values[0] =
1358*2264Sjacobs 								strdup(value);
1359*2264Sjacobs 					(*attrs)[i]->mod_values[1] = NULL;
1360*2264Sjacobs 					(*attrs)[i+1] = NULL;
1361*2264Sjacobs 				}
1362*2264Sjacobs 				else
1363*2264Sjacobs 				{
1364*2264Sjacobs 					result = NSL_ERR_MEMORY;
1365*2264Sjacobs 				}
1366*2264Sjacobs 			}
1367*2264Sjacobs 			else
1368*2264Sjacobs 			if ((*attrs)[i] != NULL)
1369*2264Sjacobs 			{
1370*2264Sjacobs 				/* value is null so do an attribute delete */
1371*2264Sjacobs 
1372*2264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_DELETE;
1373*2264Sjacobs 				(*attrs)[i]->mod_type = strdup(type);
1374*2264Sjacobs 				(*attrs)[i]->mod_values = NULL;
1375*2264Sjacobs 				(*attrs)[i+1] = NULL;
1376*2264Sjacobs 			}
1377*2264Sjacobs 			else
1378*2264Sjacobs 			{
1379*2264Sjacobs 				result = NSL_ERR_MEMORY; /* malloc failed */
1380*2264Sjacobs 			}
1381*2264Sjacobs 		}
1382*2264Sjacobs 
1383*2264Sjacobs 		else
1384*2264Sjacobs 		{
1385*2264Sjacobs 			/* Found an existing entry so add value to it */
1386*2264Sjacobs 
1387*2264Sjacobs 			if (value != NULL)
1388*2264Sjacobs 			{
1389*2264Sjacobs 			    /* add value to attribute's replace list */
1390*2264Sjacobs 
1391*2264Sjacobs 			    if ((*attrs)[i]->mod_op == LDAP_MOD_REPLACE)
1392*2264Sjacobs 			    {
1393*2264Sjacobs 				for (j = 0;
1394*2264Sjacobs 				    (*attrs)[i]->mod_values[j] != NULL; j++);
1395*2264Sjacobs 
1396*2264Sjacobs 				(*attrs)[i]->mod_values =
1397*2264Sjacobs 				(char **)realloc((*attrs)[i]->mod_values,
1398*2264Sjacobs 						(j + 2) * sizeof (char *));
1399*2264Sjacobs 				if ((*attrs)[i]->mod_values != NULL)
1400*2264Sjacobs 				{
1401*2264Sjacobs 					(*attrs)[i]->mod_values[j] =
1402*2264Sjacobs 								strdup(value);
1403*2264Sjacobs 					(*attrs)[i]->mod_values[j+1] = NULL;
1404*2264Sjacobs 				}
1405*2264Sjacobs 				else
1406*2264Sjacobs 				{
1407*2264Sjacobs 					result = NSL_ERR_MEMORY;
1408*2264Sjacobs 				}
1409*2264Sjacobs 			    }
1410*2264Sjacobs 			    else
1411*2264Sjacobs 			    {
1412*2264Sjacobs 				/* Delete and replace not allowed */
1413*2264Sjacobs 				result = NSL_ERR_MULTIOP;
1414*2264Sjacobs 			    }
1415*2264Sjacobs 			}
1416*2264Sjacobs 
1417*2264Sjacobs 			else
1418*2264Sjacobs 			{
1419*2264Sjacobs 				/*
1420*2264Sjacobs 				 * attribute delete - so free any existing
1421*2264Sjacobs 				 * entries in the value array
1422*2264Sjacobs 				 */
1423*2264Sjacobs 
1424*2264Sjacobs 				(*attrs)[i]->mod_op = LDAP_MOD_DELETE;
1425*2264Sjacobs 
1426*2264Sjacobs 				if ((*attrs)[i]->mod_values != NULL)
1427*2264Sjacobs 				{
1428*2264Sjacobs 					for (j = 0;
1429*2264Sjacobs 					    (*attrs)[i]->mod_values[j] != NULL;
1430*2264Sjacobs 					    j++)
1431*2264Sjacobs 					{
1432*2264Sjacobs 					    free((*attrs)[i]->mod_values[j]);
1433*2264Sjacobs 					}
1434*2264Sjacobs 
1435*2264Sjacobs 					free((*attrs)[i]->mod_values);
1436*2264Sjacobs 					(*attrs)[i]->mod_values = NULL;
1437*2264Sjacobs 				}
1438*2264Sjacobs 			}
1439*2264Sjacobs 		}
1440*2264Sjacobs 	}
1441*2264Sjacobs 
1442*2264Sjacobs 	return (result);
1443*2264Sjacobs } /* _modLDAPmodValue */
1444*2264Sjacobs 
1445*2264Sjacobs 
1446*2264Sjacobs 
1447*2264Sjacobs 
1448*2264Sjacobs 
1449*2264Sjacobs /*
1450*2264Sjacobs  * *****************************************************************************
1451*2264Sjacobs  *
1452*2264Sjacobs  * Function:    _constructAddLDAPMod()
1453*2264Sjacobs  *
1454*2264Sjacobs  * Description: For the given attribute list construct an
1455*2264Sjacobs  *              LDAPMod array for the printer object to be added. Default
1456*2264Sjacobs  *              attribute values are included.
1457*2264Sjacobs  *
1458*2264Sjacobs  * Parameters:
1459*2264Sjacobs  * Input:
1460*2264Sjacobs  *              uchar_t *printerName - Name of printer to be added
1461*2264Sjacobs  *              char    **attrList - user specified attribute values list
1462*2264Sjacobs  * Output:      LDAPMod ***attrs  - pointer to the constructed array
1463*2264Sjacobs  *
1464*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = constructed okay
1465*2264Sjacobs  *
1466*2264Sjacobs  * *****************************************************************************
1467*2264Sjacobs  */
1468*2264Sjacobs 
1469*2264Sjacobs static NSL_RESULT
1470*2264Sjacobs _constructAddLDAPMod(uchar_t *printerName, char **attrList,  LDAPMod ***attrs)
1471*2264Sjacobs 
1472*2264Sjacobs {
1473*2264Sjacobs 	NSL_RESULT result = NSL_ERROR;
1474*2264Sjacobs 	int len = 0;
1475*2264Sjacobs 	char **p = NULL;
1476*2264Sjacobs 	char *value = NULL;
1477*2264Sjacobs 	char *attr = NULL;
1478*2264Sjacobs 
1479*2264Sjacobs 	/* ---------- */
1480*2264Sjacobs 
1481*2264Sjacobs 	if ((printerName != NULL) &&
1482*2264Sjacobs 	    ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL))
1483*2264Sjacobs 	{
1484*2264Sjacobs 		*attrs = NULL;
1485*2264Sjacobs 
1486*2264Sjacobs 		/*
1487*2264Sjacobs 		 * setup printer object attribute values in an LDAPMod structure
1488*2264Sjacobs 		 */
1489*2264Sjacobs 		result = _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_TOP);
1490*2264Sjacobs 		if (result == NSL_OK)
1491*2264Sjacobs 		{
1492*2264Sjacobs 			/* Structural Objectclass */
1493*2264Sjacobs 			result =
1494*2264Sjacobs 			    _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_PSERVICE);
1495*2264Sjacobs 		}
1496*2264Sjacobs 		if (result == NSL_OK)
1497*2264Sjacobs 		{
1498*2264Sjacobs 			result = _addLDAPmodValue(attrs,
1499*2264Sjacobs 						ATTR_OCLASS, OCV_PABSTRACT);
1500*2264Sjacobs 		}
1501*2264Sjacobs 		if (result == NSL_OK)
1502*2264Sjacobs 		{
1503*2264Sjacobs 			result = _addLDAPmodValue(attrs,
1504*2264Sjacobs 						ATTR_OCLASS, OCV_SUNPRT);
1505*2264Sjacobs 		}
1506*2264Sjacobs 		if (result == NSL_OK)
1507*2264Sjacobs 		{
1508*2264Sjacobs 			result = _addLDAPmodValue(attrs,
1509*2264Sjacobs 					ATTR_PNAME, (char *)printerName);
1510*2264Sjacobs 		}
1511*2264Sjacobs 
1512*2264Sjacobs 		/*
1513*2264Sjacobs 		 * Now work through the user supplied attribute
1514*2264Sjacobs 		 * values list and add them into the LDAPMod array
1515*2264Sjacobs 		 */
1516*2264Sjacobs 
1517*2264Sjacobs 		for (p = attrList;
1518*2264Sjacobs 			(p != NULL) && (*p != NULL) && (result == NSL_OK); p++)
1519*2264Sjacobs 		{
1520*2264Sjacobs 			/* get length of this key word */
1521*2264Sjacobs 
1522*2264Sjacobs 			for (len = 0;
1523*2264Sjacobs 			    ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
1524*2264Sjacobs 
1525*2264Sjacobs 			if ((strlen(*p) > len+1))
1526*2264Sjacobs 			{
1527*2264Sjacobs 				attr = strdup(*p);
1528*2264Sjacobs 				attr[len] = '\0';
1529*2264Sjacobs 				value = strdup(&attr[len+1]);
1530*2264Sjacobs 
1531*2264Sjacobs 				/* handle specific Key Value Pairs (KVP) */
1532*2264Sjacobs 
1533*2264Sjacobs 				if (strcasecmp(attr, NS_KEY_BSDADDR) == 0)
1534*2264Sjacobs 				{
1535*2264Sjacobs 					/* use LDAP attribute name */
1536*2264Sjacobs 					free(attr);
1537*2264Sjacobs 					attr = strdup(ATTR_BSDADDR);
1538*2264Sjacobs 				}
1539*2264Sjacobs 				else
1540*2264Sjacobs 				if (_attrInLDAPList(attr) == 0)
1541*2264Sjacobs 				{
1542*2264Sjacobs 					/*
1543*2264Sjacobs 					 * Non-LDAP attribute so use LDAP
1544*2264Sjacobs 					 * KVP attribute and the given KVP
1545*2264Sjacobs 					 * as the value, ie.
1546*2264Sjacobs 					 * sun-printer-kvp=description=printer
1547*2264Sjacobs 					 */
1548*2264Sjacobs 					free(attr);
1549*2264Sjacobs 					attr = strdup(ATTR_KVP);
1550*2264Sjacobs 					value = strdup(*p);
1551*2264Sjacobs 				}
1552*2264Sjacobs 
1553*2264Sjacobs 				/* add it into the LDAPMod array */
1554*2264Sjacobs 
1555*2264Sjacobs 				result = _addLDAPmodValue(attrs, attr, value);
1556*2264Sjacobs 
1557*2264Sjacobs 				free(attr);
1558*2264Sjacobs 				free(value);
1559*2264Sjacobs 			}
1560*2264Sjacobs 		} /* for */
1561*2264Sjacobs 
1562*2264Sjacobs 		if ((result != NSL_OK) && (*attrs != NULL))
1563*2264Sjacobs 		{
1564*2264Sjacobs 			(void) ldap_mods_free(*attrs, 1);
1565*2264Sjacobs 			attrs = NULL;
1566*2264Sjacobs 		}
1567*2264Sjacobs 	}
1568*2264Sjacobs 	else
1569*2264Sjacobs 	{
1570*2264Sjacobs 		result = NSL_ERR_INTERNAL;
1571*2264Sjacobs 	}
1572*2264Sjacobs 
1573*2264Sjacobs 	return (result);
1574*2264Sjacobs } /* _constructAddLDAPMod */
1575*2264Sjacobs 
1576*2264Sjacobs 
1577*2264Sjacobs 
1578*2264Sjacobs 
1579*2264Sjacobs 
1580*2264Sjacobs 
1581*2264Sjacobs 
1582*2264Sjacobs /*
1583*2264Sjacobs  * *****************************************************************************
1584*2264Sjacobs  *
1585*2264Sjacobs  * Function:    _constructModLDAPMod()
1586*2264Sjacobs  *
1587*2264Sjacobs  * Description: For the given modify attribute list, construct an
1588*2264Sjacobs  *              LDAPMod array for the printer object to be modified
1589*2264Sjacobs  *
1590*2264Sjacobs  * Parameters:
1591*2264Sjacobs  * Input:       uchar_t *printerName - name of printer to be modified
1592*2264Sjacobs  *              int     sunPrinter - Boolean; object is a sunPrinter
1593*2264Sjacobs  *              char    **attrList - user specified attribute values list
1594*2264Sjacobs  *              char    ***oldKVPList - current list of KVP values on object
1595*2264Sjacobs  * Output:      LDAPMod ***attrs  - pointer to the constructed array
1596*2264Sjacobs  *
1597*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = constructed okay
1598*2264Sjacobs  *
1599*2264Sjacobs  * *****************************************************************************
1600*2264Sjacobs  */
1601*2264Sjacobs 
1602*2264Sjacobs static NSL_RESULT
1603*2264Sjacobs _constructModLDAPMod(uchar_t *printerName, int sunPrinter, char **attrList,
1604*2264Sjacobs 			char ***oldKVPList, LDAPMod ***attrs)
1605*2264Sjacobs 
1606*2264Sjacobs {
1607*2264Sjacobs 	NSL_RESULT result = NSL_OK;
1608*2264Sjacobs 	int len = 0;
1609*2264Sjacobs 	int kvpUpdated = 0;
1610*2264Sjacobs 	int kvpExists = 0;
1611*2264Sjacobs 	char **p = NULL;
1612*2264Sjacobs 	char *value = NULL;
1613*2264Sjacobs 	char *attr = NULL;
1614*2264Sjacobs 
1615*2264Sjacobs 	/* ---------- */
1616*2264Sjacobs 
1617*2264Sjacobs 	if ((printerName != NULL) &&
1618*2264Sjacobs 	    ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL))
1619*2264Sjacobs 	{
1620*2264Sjacobs 		*attrs = NULL;
1621*2264Sjacobs 
1622*2264Sjacobs 		if ((oldKVPList != NULL) && (*oldKVPList != NULL))
1623*2264Sjacobs 		{
1624*2264Sjacobs 			kvpExists = 1;
1625*2264Sjacobs 		}
1626*2264Sjacobs 
1627*2264Sjacobs 		if (!sunPrinter)
1628*2264Sjacobs 		{
1629*2264Sjacobs 			/*
1630*2264Sjacobs 			 * The object was previously not a sunPrinter, so
1631*2264Sjacobs 			 * add the required objectclass attribute value, and
1632*2264Sjacobs 			 * ensure it has the printername attribute.
1633*2264Sjacobs 			 */
1634*2264Sjacobs 			result = _addLDAPmodValue(attrs,
1635*2264Sjacobs 						ATTR_OCLASS, OCV_SUNPRT);
1636*2264Sjacobs 			if (result == NSL_OK)
1637*2264Sjacobs 			{
1638*2264Sjacobs 				result = _modLDAPmodValue(attrs,
1639*2264Sjacobs 					    ATTR_PNAME, (char *)printerName);
1640*2264Sjacobs 			}
1641*2264Sjacobs 		}
1642*2264Sjacobs 
1643*2264Sjacobs 		/*
1644*2264Sjacobs 		 * work through the user supplied attribute
1645*2264Sjacobs 		 * values list and add them into the LDAPMod array depending
1646*2264Sjacobs 		 * on if they are a replace or delete attribute operation,
1647*2264Sjacobs 		 * a "null value" means delete.
1648*2264Sjacobs 		 */
1649*2264Sjacobs 
1650*2264Sjacobs 		for (p = attrList;
1651*2264Sjacobs 			(p != NULL) && (*p != NULL) && (result == NSL_OK); p++)
1652*2264Sjacobs 		{
1653*2264Sjacobs 			/* get length of this key word */
1654*2264Sjacobs 
1655*2264Sjacobs 			for (len = 0;
1656*2264Sjacobs 			    ((*p)[len] != '=') && ((*p)[len] != '\0'); len++);
1657*2264Sjacobs 
1658*2264Sjacobs 			if ((strlen(*p) > len+1))
1659*2264Sjacobs 			{
1660*2264Sjacobs 				attr = strdup(*p);
1661*2264Sjacobs 				attr[len] = '\0';
1662*2264Sjacobs 				value = strdup(&attr[len+1]);
1663*2264Sjacobs 
1664*2264Sjacobs 				/* handle specific Key Value Pairs (KVP) */
1665*2264Sjacobs 
1666*2264Sjacobs 				if ((_attrInLDAPList(attr) == 0) &&
1667*2264Sjacobs 					(strcasecmp(attr, NS_KEY_BSDADDR) != 0))
1668*2264Sjacobs 				{
1669*2264Sjacobs 					/*
1670*2264Sjacobs 					 * Non-LDAP attribute so use LDAP
1671*2264Sjacobs 					 * KVP attribute and the given KVP as
1672*2264Sjacobs 					 * the value, ie.
1673*2264Sjacobs 					 * sun-printer-kvp=description=printer
1674*2264Sjacobs 					 */
1675*2264Sjacobs 					result = _modAttrKVP(*p, oldKVPList);
1676*2264Sjacobs 					kvpUpdated = 1;
1677*2264Sjacobs 				}
1678*2264Sjacobs 
1679*2264Sjacobs 				else
1680*2264Sjacobs 				{
1681*2264Sjacobs 					if (strcasecmp(attr, NS_KEY_BSDADDR) ==
1682*2264Sjacobs 									0)
1683*2264Sjacobs 					{
1684*2264Sjacobs 						/*
1685*2264Sjacobs 						 * use LDAP bsdaddr attribute
1686*2264Sjacobs 						 * name
1687*2264Sjacobs 						 */
1688*2264Sjacobs 						free(attr);
1689*2264Sjacobs 						attr = strdup(ATTR_BSDADDR);
1690*2264Sjacobs 					}
1691*2264Sjacobs 
1692*2264Sjacobs 					/*
1693*2264Sjacobs 					 * else
1694*2264Sjacobs 					 *   use the supplied attribute name
1695*2264Sjacobs 					 */
1696*2264Sjacobs 
1697*2264Sjacobs 					/* add it into the LDAPMod array */
1698*2264Sjacobs 
1699*2264Sjacobs 					result = _modLDAPmodValue(attrs,
1700*2264Sjacobs 								attr, value);
1701*2264Sjacobs 				}
1702*2264Sjacobs 
1703*2264Sjacobs 				free(attr);
1704*2264Sjacobs 				free(value);
1705*2264Sjacobs 			}
1706*2264Sjacobs 
1707*2264Sjacobs 			else
1708*2264Sjacobs 			if (strlen(*p) >= 1)
1709*2264Sjacobs 			{
1710*2264Sjacobs 				/* handle attribute DELETE request */
1711*2264Sjacobs 
1712*2264Sjacobs 				attr = strdup(*p);
1713*2264Sjacobs 				if (attr[len] == '=')
1714*2264Sjacobs 				{
1715*2264Sjacobs 					/* terminate "attribute=" */
1716*2264Sjacobs 					attr[len] = '\0';
1717*2264Sjacobs 				}
1718*2264Sjacobs 
1719*2264Sjacobs 				/* handle specific Key Value Pairs (KVP) */
1720*2264Sjacobs 
1721*2264Sjacobs 				if (strcasecmp(attr, NS_KEY_BSDADDR) == 0)
1722*2264Sjacobs 				{
1723*2264Sjacobs 					/* use LDAP bsdaddr attribute name */
1724*2264Sjacobs 					result = _modLDAPmodValue(attrs,
1725*2264Sjacobs 							ATTR_BSDADDR, NULL);
1726*2264Sjacobs 				}
1727*2264Sjacobs 				else
1728*2264Sjacobs 				if (_attrInLDAPList(attr) == 0)
1729*2264Sjacobs 				{
1730*2264Sjacobs 					/*
1731*2264Sjacobs 					 * Non-LDAP kvp, so sort items
1732*2264Sjacobs 					 * in the kvp list
1733*2264Sjacobs 					 */
1734*2264Sjacobs 					result = _modAttrKVP(*p, oldKVPList);
1735*2264Sjacobs 					kvpUpdated = 1;
1736*2264Sjacobs 				}
1737*2264Sjacobs 				else
1738*2264Sjacobs 				{
1739*2264Sjacobs 					result = _modLDAPmodValue(attrs,
1740*2264Sjacobs 							attr, NULL);
1741*2264Sjacobs 				}
1742*2264Sjacobs 
1743*2264Sjacobs 				free(attr);
1744*2264Sjacobs 			}
1745*2264Sjacobs 		} /* for */
1746*2264Sjacobs 
1747*2264Sjacobs 		if ((result == NSL_OK) && (kvpUpdated))
1748*2264Sjacobs 		{
1749*2264Sjacobs 			result = _attrAddKVP(attrs, *oldKVPList, kvpExists);
1750*2264Sjacobs 		}
1751*2264Sjacobs 
1752*2264Sjacobs 		if ((result != NSL_OK) && (*attrs != NULL))
1753*2264Sjacobs 		{
1754*2264Sjacobs 			(void) ldap_mods_free(*attrs, 1);
1755*2264Sjacobs 			*attrs = NULL;
1756*2264Sjacobs 		}
1757*2264Sjacobs 	}
1758*2264Sjacobs 	else
1759*2264Sjacobs 	{
1760*2264Sjacobs 		result = NSL_ERR_INTERNAL;
1761*2264Sjacobs 	}
1762*2264Sjacobs 
1763*2264Sjacobs 	return (result);
1764*2264Sjacobs } /* _constructModLDAPMod */
1765*2264Sjacobs 
1766*2264Sjacobs 
1767*2264Sjacobs 
1768*2264Sjacobs 
1769*2264Sjacobs 
1770*2264Sjacobs 
1771*2264Sjacobs /*
1772*2264Sjacobs  * *****************************************************************************
1773*2264Sjacobs  *
1774*2264Sjacobs  * Function:    _compareURIinDNs()
1775*2264Sjacobs  *
1776*2264Sjacobs  * Description: For the 2 given printer object DNs compare the naming part
1777*2264Sjacobs  *              part of the DN (printer-uri) to see if they are the same.
1778*2264Sjacobs  *
1779*2264Sjacobs  * Note:        This function only returns "compare failed" if their URI don't
1780*2264Sjacobs  *              compare. Problems with the dn etc., return a good compare
1781*2264Sjacobs  *              because I don't want us to create a new object for these
1782*2264Sjacobs  *
1783*2264Sjacobs  * Parameters:
1784*2264Sjacobs  * Input:       uchar_t *dn1
1785*2264Sjacobs  *              uchar_t *dn2
1786*2264Sjacobs  * Output:      None
1787*2264Sjacobs  *
1788*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = URIs are the same
1789*2264Sjacobs  *
1790*2264Sjacobs  * *****************************************************************************
1791*2264Sjacobs  */
1792*2264Sjacobs 
1793*2264Sjacobs static NSL_RESULT
1794*2264Sjacobs _compareURIinDNs(uchar_t *dn1, uchar_t *dn2)
1795*2264Sjacobs 
1796*2264Sjacobs {
1797*2264Sjacobs 	NSL_RESULT result = NSL_OK;
1798*2264Sjacobs 	uchar_t *DN1 = NULL;
1799*2264Sjacobs 	uchar_t *DN2 = NULL;
1800*2264Sjacobs 	char *p1 = NULL;
1801*2264Sjacobs 	char *p2 = NULL;
1802*2264Sjacobs 
1803*2264Sjacobs 	/* --------- */
1804*2264Sjacobs 
1805*2264Sjacobs 	if ((dn1 != NULL) && (dn2 != NULL))
1806*2264Sjacobs 	{
1807*2264Sjacobs 		DN1 = (uchar_t *)strdup((char *)dn1);
1808*2264Sjacobs 		DN2 = (uchar_t *)strdup((char *)dn2);
1809*2264Sjacobs 
1810*2264Sjacobs 		/* terminate each string after the printer-uri */
1811*2264Sjacobs 
1812*2264Sjacobs 		p1 = strstr((char *)DN1, PCONTAINER);
1813*2264Sjacobs 		/* move back to the comma */
1814*2264Sjacobs 		while ((p1 != NULL) && (*p1 != ',') && (p1 >= (char *)DN1))
1815*2264Sjacobs 		{
1816*2264Sjacobs 			p1--;
1817*2264Sjacobs 		}
1818*2264Sjacobs 
1819*2264Sjacobs 		p2 = strstr((char *)DN2, PCONTAINER);
1820*2264Sjacobs 		/* move back to the comma */
1821*2264Sjacobs 		while ((p2 != NULL) && (*p2 != ',') && (p2 >= (char *)DN2))
1822*2264Sjacobs 		{
1823*2264Sjacobs 			p2--;
1824*2264Sjacobs 		}
1825*2264Sjacobs 
1826*2264Sjacobs 		if ((*p1 == ',') && (*p2 == ','))
1827*2264Sjacobs 		{
1828*2264Sjacobs 			*p1 = '\0';	/* re-terminate it */
1829*2264Sjacobs 			*p2 = '\0';	/* re-terminate it */
1830*2264Sjacobs 
1831*2264Sjacobs 			/* do the compare */
1832*2264Sjacobs 
1833*2264Sjacobs 			/*
1834*2264Sjacobs 			 * Note: SHOULD really normalise the 2 DNs before
1835*2264Sjacobs 			 * doing the compare
1836*2264Sjacobs 			 */
1837*2264Sjacobs #ifdef DEBUG
1838*2264Sjacobs printf("_compareURIinDNs() @1 (%s) (%s)\n", DN1, DN2);
1839*2264Sjacobs #endif
1840*2264Sjacobs 			if (strcasecmp((char *)DN1, (char *)DN2) != 0)
1841*2264Sjacobs 			{
1842*2264Sjacobs 				result = NSL_ERROR;
1843*2264Sjacobs 			}
1844*2264Sjacobs 
1845*2264Sjacobs 		}
1846*2264Sjacobs 
1847*2264Sjacobs 		free(DN1);
1848*2264Sjacobs 		free(DN2);
1849*2264Sjacobs 	}
1850*2264Sjacobs 
1851*2264Sjacobs 	return (result);
1852*2264Sjacobs } /* _compareURIinDNs */
1853*2264Sjacobs 
1854*2264Sjacobs 
1855*2264Sjacobs 
1856*2264Sjacobs 
1857*2264Sjacobs 
1858*2264Sjacobs 
1859*2264Sjacobs 
1860*2264Sjacobs /*
1861*2264Sjacobs  * *****************************************************************************
1862*2264Sjacobs  *
1863*2264Sjacobs  * Function:    _getThisNSDomainDN()
1864*2264Sjacobs  *
1865*2264Sjacobs  * Description: Get the current Name Service Domain DN
1866*2264Sjacobs  *              This is extracted from the result of executing ldaplist.
1867*2264Sjacobs  *
1868*2264Sjacobs  * Note:        Do it this way until the NS LDAP library interface is
1869*2264Sjacobs  *              made public.
1870*2264Sjacobs  *
1871*2264Sjacobs  * Parameters:
1872*2264Sjacobs  * Input:       None
1873*2264Sjacobs  * Output:      None
1874*2264Sjacobs  *
1875*2264Sjacobs  * Returns:     uchar_t*  - pointer to NS Domain DN (The caller should free this
1876*2264Sjacobs  *                          returned memory).
1877*2264Sjacobs  *
1878*2264Sjacobs  * *****************************************************************************
1879*2264Sjacobs  */
1880*2264Sjacobs 
1881*2264Sjacobs #define	LDAPLIST_D	"/usr/bin/ldaplist -d 2>&1"
1882*2264Sjacobs #define	DNID		"dn: "
1883*2264Sjacobs 
1884*2264Sjacobs static uchar_t *
1885*2264Sjacobs _getThisNSDomainDN(void)
1886*2264Sjacobs 
1887*2264Sjacobs {
1888*2264Sjacobs 	uchar_t *domainDN = NULL;
1889*2264Sjacobs 	char *cp = NULL;
1890*2264Sjacobs 	char buf[BUFSIZ] = "";
1891*2264Sjacobs 
1892*2264Sjacobs 	/* --------- */
1893*2264Sjacobs 
1894*2264Sjacobs 	if (_popen(LDAPLIST_D, buf, sizeof (buf)) == 0)
1895*2264Sjacobs 	{
1896*2264Sjacobs 		if ((cp = strstr(buf, DNID)) != NULL)
1897*2264Sjacobs 		{
1898*2264Sjacobs 			cp += strlen(DNID);  /* increment past "dn: " label */
1899*2264Sjacobs 			domainDN = (uchar_t *)strdup(cp);
1900*2264Sjacobs 
1901*2264Sjacobs 			if ((cp = strchr((char *)domainDN, '\n')) != NULL)
1902*2264Sjacobs 			{
1903*2264Sjacobs 				*cp = '\0'; /* terminate it */
1904*2264Sjacobs 			}
1905*2264Sjacobs 		}
1906*2264Sjacobs 	}
1907*2264Sjacobs 
1908*2264Sjacobs 	return (domainDN);
1909*2264Sjacobs } /* _getThisNSDomainDN */
1910*2264Sjacobs 
1911*2264Sjacobs 
1912*2264Sjacobs 
1913*2264Sjacobs 
1914*2264Sjacobs 
1915*2264Sjacobs /*
1916*2264Sjacobs  * *****************************************************************************
1917*2264Sjacobs  *
1918*2264Sjacobs  * Function:    _popen()
1919*2264Sjacobs  *
1920*2264Sjacobs  * Description: General popen function. The caller should always use a full
1921*2264Sjacobs  *              path cmd.
1922*2264Sjacobs  *
1923*2264Sjacobs  * Parameters:
1924*2264Sjacobs  * Input:       char *cmd - command line to execute
1925*2264Sjacobs  *              char *buffer - ptr to buffer to put result in
1926*2264Sjacobs  *              int  size - size of result buffer
1927*2264Sjacobs  * Output:      None
1928*2264Sjacobs  *
1929*2264Sjacobs  * Returns:     int - 0 = opened okay
1930*2264Sjacobs  *
1931*2264Sjacobs  * *****************************************************************************
1932*2264Sjacobs  */
1933*2264Sjacobs 
1934*2264Sjacobs static int
1935*2264Sjacobs _popen(char *cmd, char *buffer, int size)
1936*2264Sjacobs 
1937*2264Sjacobs {
1938*2264Sjacobs 	int result = -1;
1939*2264Sjacobs 	int rsize = 0;
1940*2264Sjacobs 	FILE *fptr;
1941*2264Sjacobs 	char safe_cmd[BUFSIZ];
1942*2264Sjacobs 	char linebuf[BUFSIZ];
1943*2264Sjacobs 
1944*2264Sjacobs 	/* -------- */
1945*2264Sjacobs 
1946*2264Sjacobs 	if ((cmd != NULL) && (buffer != NULL) && (size != 0))
1947*2264Sjacobs 	{
1948*2264Sjacobs 		(void) strcpy(buffer, "");
1949*2264Sjacobs 		(void) strcpy(linebuf, "");
1950*2264Sjacobs 		(void) snprintf(safe_cmd, BUFSIZ, "IFS=' \t'; %s", cmd);
1951*2264Sjacobs 
1952*2264Sjacobs 		if ((fptr = popen(safe_cmd, "r")) != NULL)
1953*2264Sjacobs 		{
1954*2264Sjacobs 			while ((fgets(linebuf, BUFSIZ, fptr) != NULL) &&
1955*2264Sjacobs 							(rsize  < size))
1956*2264Sjacobs 			{
1957*2264Sjacobs 				rsize = strlcat(buffer, linebuf, size);
1958*2264Sjacobs 				if (rsize >= size)
1959*2264Sjacobs 				{
1960*2264Sjacobs 					/* result is too long */
1961*2264Sjacobs 					(void) memset(buffer, '\0', size);
1962*2264Sjacobs 				}
1963*2264Sjacobs 			}
1964*2264Sjacobs 
1965*2264Sjacobs 			if (strlen(buffer) > 0)
1966*2264Sjacobs 			{
1967*2264Sjacobs 				result = 0;
1968*2264Sjacobs 			}
1969*2264Sjacobs 
1970*2264Sjacobs 			(void) pclose(fptr);
1971*2264Sjacobs 		}
1972*2264Sjacobs 	}
1973*2264Sjacobs 
1974*2264Sjacobs 	return (result);
1975*2264Sjacobs } /* popen */
1976*2264Sjacobs 
1977*2264Sjacobs 
1978*2264Sjacobs /*
1979*2264Sjacobs  * *****************************************************************************
1980*2264Sjacobs  *
1981*2264Sjacobs  * Function:    _attrInList()
1982*2264Sjacobs  *
1983*2264Sjacobs  * Description: For the given list check if the attribute is it
1984*2264Sjacobs  *
1985*2264Sjacobs  * Parameters:
1986*2264Sjacobs  * Input:       char *attr   - attribute to check
1987*2264Sjacobs  *              char **list  - list of attributes to check against
1988*2264Sjacobs  * Output:      None
1989*2264Sjacobs  *
1990*2264Sjacobs  * Returns:     int - TRUE = attr found in list
1991*2264Sjacobs  *
1992*2264Sjacobs  * *****************************************************************************
1993*2264Sjacobs  */
1994*2264Sjacobs 
1995*2264Sjacobs static int
1996*2264Sjacobs _attrInList(char *attr, const char **list)
1997*2264Sjacobs 
1998*2264Sjacobs {
1999*2264Sjacobs 	int result = 0;
2000*2264Sjacobs 	int j;
2001*2264Sjacobs 
2002*2264Sjacobs 	/* ------- */
2003*2264Sjacobs 
2004*2264Sjacobs 	if ((attr != NULL) && (list != NULL))
2005*2264Sjacobs 	{
2006*2264Sjacobs 		for (j = 0; (list[j] != NULL) && (result != 1); j++)
2007*2264Sjacobs 		{
2008*2264Sjacobs 			if (strcasecmp(list[j], attr) == 0)
2009*2264Sjacobs 			{
2010*2264Sjacobs 				result = 1; /* found */
2011*2264Sjacobs 			}
2012*2264Sjacobs 		}
2013*2264Sjacobs 	}
2014*2264Sjacobs 
2015*2264Sjacobs 	return (result);
2016*2264Sjacobs } /* _attrInList */
2017*2264Sjacobs 
2018*2264Sjacobs 
2019*2264Sjacobs 
2020*2264Sjacobs 
2021*2264Sjacobs /*
2022*2264Sjacobs  * *****************************************************************************
2023*2264Sjacobs  *
2024*2264Sjacobs  * Function:    _attrInLDAPList()
2025*2264Sjacobs  *
2026*2264Sjacobs  * Description: Checks to see if the given attribute is an LDAP printing
2027*2264Sjacobs  *              attribute, ie. is either in an IPP objectclass or the
2028*2264Sjacobs  *              sun printer objectclass. Note: some attributes are handled
2029*2264Sjacobs  *              specifically outside this function, so are excluded from
2030*2264Sjacobs  *              the lists that are checked.
2031*2264Sjacobs  *
2032*2264Sjacobs  * Parameters:
2033*2264Sjacobs  * Input:       char *attr    - attribute to check
2034*2264Sjacobs  * Output:      None
2035*2264Sjacobs  *
2036*2264Sjacobs  * Returns:     int - TRUE = attr found in list
2037*2264Sjacobs  *
2038*2264Sjacobs  * *****************************************************************************
2039*2264Sjacobs  */
2040*2264Sjacobs 
2041*2264Sjacobs static int
2042*2264Sjacobs _attrInLDAPList(char *attr)
2043*2264Sjacobs 
2044*2264Sjacobs {
2045*2264Sjacobs 	int result = 0;
2046*2264Sjacobs 
2047*2264Sjacobs 	/* ------- */
2048*2264Sjacobs 
2049*2264Sjacobs 	if (_attrInList(attr, nsl_attr_printerService))
2050*2264Sjacobs 	{
2051*2264Sjacobs 		result = 1;	/* in list */
2052*2264Sjacobs 	}
2053*2264Sjacobs 	else
2054*2264Sjacobs 	if (_attrInList(attr, nsl_attr_printerIPP))
2055*2264Sjacobs 	{
2056*2264Sjacobs 		result = 1;	/* in list */
2057*2264Sjacobs 	}
2058*2264Sjacobs 	else
2059*2264Sjacobs 	if (_attrInList(attr, nsl_attr_sunPrinter))
2060*2264Sjacobs 	{
2061*2264Sjacobs 		result = 1;	/* in list */
2062*2264Sjacobs 	}
2063*2264Sjacobs 
2064*2264Sjacobs 	return (result);
2065*2264Sjacobs } /* _attrInLDAPList */
2066*2264Sjacobs 
2067*2264Sjacobs 
2068*2264Sjacobs 
2069*2264Sjacobs 
2070*2264Sjacobs /*
2071*2264Sjacobs  * *****************************************************************************
2072*2264Sjacobs  *
2073*2264Sjacobs  * Function:    _getCurrentKVPValues()
2074*2264Sjacobs  *
2075*2264Sjacobs  * Description: For the given printer object read the current set of values
2076*2264Sjacobs  *              the object has for the sun-printer-kvp (Key Value pair)
2077*2264Sjacobs  *
2078*2264Sjacobs  * Parameters:
2079*2264Sjacobs  * Input:       LDAP *ld       - existing ldap connection descriptor
2080*2264Sjacobs  *              char *objectDN - DN to search for
2081*2264Sjacobs  * Output:      char ***list   - returned set of kvp values
2082*2264Sjacobs  *
2083*2264Sjacobs  * Result:      NSL_RESULT - NSL_OK = object exists
2084*2264Sjacobs  *
2085*2264Sjacobs  * *****************************************************************************
2086*2264Sjacobs  */
2087*2264Sjacobs 
2088*2264Sjacobs static NSL_RESULT
2089*2264Sjacobs _getCurrentKVPValues(LDAP *ld, uchar_t *objectDN, char ***list)
2090*2264Sjacobs 
2091*2264Sjacobs {
2092*2264Sjacobs 	NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER;
2093*2264Sjacobs 	int sresult = LDAP_NO_SUCH_OBJECT;
2094*2264Sjacobs 	int i = 0;
2095*2264Sjacobs 	LDAPMessage *ldapMsg;
2096*2264Sjacobs 	char *requiredAttrs[2] = { ATTR_KVP, NULL };
2097*2264Sjacobs 	LDAPMessage *ldapEntry = NULL;
2098*2264Sjacobs 	char *entryAttrib = NULL;
2099*2264Sjacobs 	char **attribValues = NULL;
2100*2264Sjacobs 	BerElement *berElement = NULL;
2101*2264Sjacobs 
2102*2264Sjacobs 	/* ---------- */
2103*2264Sjacobs 
2104*2264Sjacobs 	if ((list != NULL) && (ld != NULL) && (objectDN != NULL))
2105*2264Sjacobs 	{
2106*2264Sjacobs 		/* search for this Printer in the directory */
2107*2264Sjacobs 
2108*2264Sjacobs 		sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE,
2109*2264Sjacobs 				"(objectclass=*)", requiredAttrs, 0, &ldapMsg);
2110*2264Sjacobs 		if (sresult == LDAP_SUCCESS)
2111*2264Sjacobs 		{
2112*2264Sjacobs 			/*
2113*2264Sjacobs 			 * check that the object exists and extract its
2114*2264Sjacobs 			 * KVP attribute values
2115*2264Sjacobs 			 */
2116*2264Sjacobs 			ldapEntry = ldap_first_entry(ld, ldapMsg);
2117*2264Sjacobs 			if (ldapEntry != NULL)
2118*2264Sjacobs 			{
2119*2264Sjacobs 				entryAttrib = ldap_first_attribute(ld,
2120*2264Sjacobs 							ldapEntry, &berElement);
2121*2264Sjacobs 				if ((entryAttrib != NULL) &&
2122*2264Sjacobs 				    (strcasecmp(entryAttrib, ATTR_KVP) == 0))
2123*2264Sjacobs 
2124*2264Sjacobs 				{
2125*2264Sjacobs #ifdef DEBUG
2126*2264Sjacobs printf("Attribute: %s, its values are:\n", entryAttrib);
2127*2264Sjacobs #endif
2128*2264Sjacobs 					/*
2129*2264Sjacobs 					 * add each KVP value to the list
2130*2264Sjacobs 					 * that we will return
2131*2264Sjacobs 					 */
2132*2264Sjacobs 					attribValues = ldap_get_values(
2133*2264Sjacobs 						ld, ldapEntry, entryAttrib);
2134*2264Sjacobs 					for (i = 0;
2135*2264Sjacobs 						attribValues[i] != NULL; i++)
2136*2264Sjacobs 					{
2137*2264Sjacobs 					    *list = (char **)
2138*2264Sjacobs 						list_append((void **)*list,
2139*2264Sjacobs 						    strdup(attribValues[i]));
2140*2264Sjacobs #ifdef DEBUG
2141*2264Sjacobs printf("\t%s\n", attribValues[i]);
2142*2264Sjacobs #endif
2143*2264Sjacobs 					}
2144*2264Sjacobs 					(void) ldap_value_free(attribValues);
2145*2264Sjacobs 				}
2146*2264Sjacobs 
2147*2264Sjacobs 				if ((entryAttrib != NULL) &&
2148*2264Sjacobs 				    (berElement != NULL))
2149*2264Sjacobs 				{
2150*2264Sjacobs 					ber_free(berElement, 0);
2151*2264Sjacobs 				}
2152*2264Sjacobs 
2153*2264Sjacobs 
2154*2264Sjacobs 				/* object found */
2155*2264Sjacobs 				result = NSL_OK;
2156*2264Sjacobs 			}
2157*2264Sjacobs 
2158*2264Sjacobs 			(void) ldap_msgfree(ldapMsg);
2159*2264Sjacobs 		}
2160*2264Sjacobs 	}
2161*2264Sjacobs 
2162*2264Sjacobs 	else
2163*2264Sjacobs 	{
2164*2264Sjacobs 		result = NSL_ERR_INTERNAL;
2165*2264Sjacobs 	}
2166*2264Sjacobs 
2167*2264Sjacobs 	return (result);
2168*2264Sjacobs } /* _getCurrentKVPValues */
2169*2264Sjacobs 
2170*2264Sjacobs 
2171*2264Sjacobs 
2172*2264Sjacobs /*
2173*2264Sjacobs  * *****************************************************************************
2174*2264Sjacobs  *
2175*2264Sjacobs  * Function:    _freeList()
2176*2264Sjacobs  *
2177*2264Sjacobs  * Description: Free the list created by list_append() where the items in
2178*2264Sjacobs  *              the list have been strdup'ed.
2179*2264Sjacobs  *
2180*2264Sjacobs  * Parameters:
2181*2264Sjacobs  * Input:       char ***list   - returned set of kvp values
2182*2264Sjacobs  *
2183*2264Sjacobs  * Result:      void
2184*2264Sjacobs  *
2185*2264Sjacobs  * *****************************************************************************
2186*2264Sjacobs  */
2187*2264Sjacobs 
2188*2264Sjacobs static void
2189*2264Sjacobs _freeList(char ***list)
2190*2264Sjacobs 
2191*2264Sjacobs {
2192*2264Sjacobs 	int i = 0;
2193*2264Sjacobs 
2194*2264Sjacobs 	/* ------ */
2195*2264Sjacobs 
2196*2264Sjacobs 	if (list != NULL)
2197*2264Sjacobs 	{
2198*2264Sjacobs 		if (*list != NULL)
2199*2264Sjacobs 		{
2200*2264Sjacobs 			for (i = 0; (*list)[i] != NULL; i++)
2201*2264Sjacobs 			{
2202*2264Sjacobs 				free((*list)[i]);
2203*2264Sjacobs 			}
2204*2264Sjacobs 			free(*list);
2205*2264Sjacobs 		}
2206*2264Sjacobs 
2207*2264Sjacobs 		*list = NULL;
2208*2264Sjacobs 	}
2209*2264Sjacobs } /* _freeList */
2210*2264Sjacobs 
2211*2264Sjacobs 
2212*2264Sjacobs 
2213*2264Sjacobs /*
2214*2264Sjacobs  * *****************************************************************************
2215*2264Sjacobs  *
2216*2264Sjacobs  * Function:    _modAttrKVP()
2217*2264Sjacobs  *
2218*2264Sjacobs  * Description: Sort out the KVP attribute value list, such that this new
2219*2264Sjacobs  *              value takes precidence over any existing value in the list.
2220*2264Sjacobs  *              The current list is updated to remove this key, and the new
2221*2264Sjacobs  *              key "value" is added to the list, eg. for
2222*2264Sjacobs  *                  value: bbb=ddddd
2223*2264Sjacobs  *                  and kvpList:
2224*2264Sjacobs  *                         aaa=yyyy
2225*2264Sjacobs  *                         bbb=zzzz
2226*2264Sjacobs  *                         ccc=xxxx
2227*2264Sjacobs  *                  the resulting kvpList is:
2228*2264Sjacobs  *                         aaa=yyyy
2229*2264Sjacobs  *                         ccc=xxxx
2230*2264Sjacobs  *                         bbb=ddddd
2231*2264Sjacobs  *
2232*2264Sjacobs  * Note:        When all new values have been handled the function _attrAddKVP()
2233*2264Sjacobs  *              must be called to add the "new list" values into the
2234*2264Sjacobs  *              LDAPMod array.
2235*2264Sjacobs  *
2236*2264Sjacobs  * Parameters:
2237*2264Sjacobs  * Input:       char *value       - Key Value Pair to process,
2238*2264Sjacobs  *                                  eg. aaaaa=hhhhh, where aaaaa is the key
2239*2264Sjacobs  *              char ***kvpList   - list of current KVP values
2240*2264Sjacobs  * Output:      char ***kvpList   - updated list of KVP values
2241*2264Sjacobs  *
2242*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = done okay
2243*2264Sjacobs  *
2244*2264Sjacobs  * *****************************************************************************
2245*2264Sjacobs  */
2246*2264Sjacobs 
2247*2264Sjacobs static NSL_RESULT
2248*2264Sjacobs _modAttrKVP(char *value, char ***kvpList)
2249*2264Sjacobs 
2250*2264Sjacobs {
2251*2264Sjacobs 	NSL_RESULT result = NSL_ERR_INTERNAL;
2252*2264Sjacobs 	int i = 0;
2253*2264Sjacobs 	int inList = 0;
2254*2264Sjacobs 	int keyDelete = 0;
2255*2264Sjacobs 	char *key = NULL;
2256*2264Sjacobs 	char **p = NULL;
2257*2264Sjacobs 	char **newList = NULL;
2258*2264Sjacobs 
2259*2264Sjacobs 	/* ------- */
2260*2264Sjacobs 
2261*2264Sjacobs 	if ((value != NULL) && (kvpList != NULL))
2262*2264Sjacobs 	{
2263*2264Sjacobs 		result = NSL_OK;
2264*2264Sjacobs 
2265*2264Sjacobs 		/* extract "key" from value */
2266*2264Sjacobs 
2267*2264Sjacobs 		key = strdup(value);
2268*2264Sjacobs 
2269*2264Sjacobs 		for (i = 0; ((key)[i] != '=') && ((key)[i] != '\0'); i++);
2270*2264Sjacobs 		key[i] = '\0'; /* terminate the key */
2271*2264Sjacobs 
2272*2264Sjacobs 		/* Is this a request to delete a "key" value */
2273*2264Sjacobs 
2274*2264Sjacobs 		if ((value[i] == '\0') || (value[i+1] == '\0'))
2275*2264Sjacobs 		{
2276*2264Sjacobs 			/* this is a request to delete the key */
2277*2264Sjacobs 			keyDelete = 1;
2278*2264Sjacobs 		}
2279*2264Sjacobs 
2280*2264Sjacobs 		if ((*kvpList != NULL) && (**kvpList != NULL))
2281*2264Sjacobs 		{
2282*2264Sjacobs 			/*
2283*2264Sjacobs 			 * for each item in the list remove it if the keys match
2284*2264Sjacobs 			 */
2285*2264Sjacobs 			for (p = *kvpList; *p != NULL; p++)
2286*2264Sjacobs 			{
2287*2264Sjacobs 				for (i = 0;
2288*2264Sjacobs 				    ((*p)[i] != '=') && ((*p)[i] != '\0'); i++);
2289*2264Sjacobs 
2290*2264Sjacobs 				if ((strlen(key) == i) &&
2291*2264Sjacobs 					(strncasecmp(*p, key, i) == 0))
2292*2264Sjacobs 				{
2293*2264Sjacobs 					inList = 1;
2294*2264Sjacobs 				}
2295*2264Sjacobs 				else
2296*2264Sjacobs 				{
2297*2264Sjacobs 					/* no match so add value to new list */
2298*2264Sjacobs 					newList = (char **)list_append(
2299*2264Sjacobs 							(void **)newList,
2300*2264Sjacobs 							strdup(*p));
2301*2264Sjacobs 				}
2302*2264Sjacobs 			}
2303*2264Sjacobs 		}
2304*2264Sjacobs 
2305*2264Sjacobs 		/*
2306*2264Sjacobs 		 * if it was not a DELETE request add the new key value into
2307*2264Sjacobs 		 * the newList, otherwise we have already removed the key
2308*2264Sjacobs 		 */
2309*2264Sjacobs 
2310*2264Sjacobs 		if (!keyDelete)
2311*2264Sjacobs 		{
2312*2264Sjacobs 			newList = (char **)list_append((void **)newList,
2313*2264Sjacobs 							strdup(value));
2314*2264Sjacobs 		}
2315*2264Sjacobs 
2316*2264Sjacobs 		if ((newList != NULL) || (inList))
2317*2264Sjacobs 		{
2318*2264Sjacobs 			/* replace old list with the newList */
2319*2264Sjacobs 			_freeList(kvpList);
2320*2264Sjacobs 			*kvpList = newList;
2321*2264Sjacobs 		}
2322*2264Sjacobs 
2323*2264Sjacobs 		free(key);
2324*2264Sjacobs 	}
2325*2264Sjacobs 
2326*2264Sjacobs 	return (result);
2327*2264Sjacobs } /* modAttrKVP */
2328*2264Sjacobs 
2329*2264Sjacobs 
2330*2264Sjacobs 
2331*2264Sjacobs 
2332*2264Sjacobs /*
2333*2264Sjacobs  * *****************************************************************************
2334*2264Sjacobs  *
2335*2264Sjacobs  * Function:    _attrAddKVP()
2336*2264Sjacobs  *
2337*2264Sjacobs  * Description: Process KVP items in the kvpList adding them to the
2338*2264Sjacobs  *              LDAPMod modify array. If the list is empty but there were
2339*2264Sjacobs  *              previously LDAP KVP values delete them.
2340*2264Sjacobs  *
2341*2264Sjacobs  * Note:        This function should only be called when all the new KVP
2342*2264Sjacobs  *              items have been processed by _modAttrKVP()
2343*2264Sjacobs  *
2344*2264Sjacobs  * Parameters:
2345*2264Sjacobs  * Input:       LDAPMod ***attrs - array to update
2346*2264Sjacobs  *              char **kvpList   - list KVP values
2347*2264Sjacobs  *              int  kvpExists   - object currently has LDAP KVP values
2348*2264Sjacobs  * Output:      None
2349*2264Sjacobs  *
2350*2264Sjacobs  * Returns:     NSL_RESULT - NSL_OK = done okay
2351*2264Sjacobs  *
2352*2264Sjacobs  * *****************************************************************************
2353*2264Sjacobs  */
2354*2264Sjacobs 
2355*2264Sjacobs static NSL_RESULT
2356*2264Sjacobs _attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists)
2357*2264Sjacobs 
2358*2264Sjacobs {
2359*2264Sjacobs 	NSL_RESULT result = NSL_OK;
2360*2264Sjacobs 
2361*2264Sjacobs 	/* ------- */
2362*2264Sjacobs 
2363*2264Sjacobs 	if (attrs != NULL)
2364*2264Sjacobs 	{
2365*2264Sjacobs 		if (kvpList != NULL)
2366*2264Sjacobs 		{
2367*2264Sjacobs 			while ((kvpList != NULL) && (*kvpList != NULL))
2368*2264Sjacobs 			{
2369*2264Sjacobs 				/* add item to LDAPMod array */
2370*2264Sjacobs 
2371*2264Sjacobs 				result =
2372*2264Sjacobs 				    _modLDAPmodValue(attrs, ATTR_KVP, *kvpList);
2373*2264Sjacobs 
2374*2264Sjacobs 				kvpList++;
2375*2264Sjacobs 			}
2376*2264Sjacobs 		}
2377*2264Sjacobs 		else
2378*2264Sjacobs 		if (kvpExists)
2379*2264Sjacobs 		{
2380*2264Sjacobs 			/*
2381*2264Sjacobs 			 * We now have no LDAP KVP values but there were
2382*2264Sjacobs 			 * some previously, so delete them
2383*2264Sjacobs 			 */
2384*2264Sjacobs 			result = _modLDAPmodValue(attrs, ATTR_KVP, NULL);
2385*2264Sjacobs 		}
2386*2264Sjacobs 	}
2387*2264Sjacobs 
2388*2264Sjacobs 	else
2389*2264Sjacobs 	{
2390*2264Sjacobs 		result = NSL_ERR_INTERNAL;
2391*2264Sjacobs 	}
2392*2264Sjacobs 
2393*2264Sjacobs 	return (result);
2394*2264Sjacobs } /* _attrAddKVP */
2395*2264Sjacobs 
2396*2264Sjacobs 
2397*2264Sjacobs 
2398*2264Sjacobs 
2399*2264Sjacobs /*
2400*2264Sjacobs  * *****************************************************************************
2401*2264Sjacobs  *
2402*2264Sjacobs  * Function:    _manageReferralCredentials()
2403*2264Sjacobs  *
2404*2264Sjacobs  * Description: This function is called if a referral request is returned by
2405*2264Sjacobs  *              the origonal LDAP server during the ldap update request call,
2406*2264Sjacobs  *              eg. ldap_add_s(), ldap_modify_s() or ldap_delete_s().
2407*2264Sjacobs  * Parameters:
2408*2264Sjacobs  * Input:       LDAP *ld      - LDAP descriptor
2409*2264Sjacobs  *              int freeit    - 0 = first call to get details
2410*2264Sjacobs  *                            - 1 = second call to free details
2411*2264Sjacobs  *                            - -1 = initial store of authentication details
2412*2264Sjacobs  * Input/Output: char **dn    - returns DN to bind to on master
2413*2264Sjacobs  *               char **credp - returns password for DN
2414*2264Sjacobs  *               int *methodp - returns authentication type, eg. simple
2415*2264Sjacobs  *
2416*2264Sjacobs  * Returns:     int - 0 = okay
2417*2264Sjacobs  *
2418*2264Sjacobs  * *****************************************************************************
2419*2264Sjacobs  */
2420*2264Sjacobs static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp,
2421*2264Sjacobs 					int *methodp, int freeit)
2422*2264Sjacobs 
2423*2264Sjacobs {
2424*2264Sjacobs 	int result = 0;
2425*2264Sjacobs 	static char *sDN = NULL;
2426*2264Sjacobs 	static char *sPasswd = NULL;
2427*2264Sjacobs 	static int  sMethod = LDAP_AUTH_SIMPLE;
2428*2264Sjacobs 
2429*2264Sjacobs 	/* -------- */
2430*2264Sjacobs 
2431*2264Sjacobs 	if (freeit == 1)
2432*2264Sjacobs 	{
2433*2264Sjacobs 		/* second call - free memory */
2434*2264Sjacobs 
2435*2264Sjacobs 		if ((dn != NULL) && (*dn != NULL))
2436*2264Sjacobs 		{
2437*2264Sjacobs 			free(*dn);
2438*2264Sjacobs 		}
2439*2264Sjacobs 
2440*2264Sjacobs 		if ((credp != NULL) && (*credp != NULL))
2441*2264Sjacobs 		{
2442*2264Sjacobs 			free(*credp);
2443*2264Sjacobs 		}
2444*2264Sjacobs 	}
2445*2264Sjacobs 
2446*2264Sjacobs 	else
2447*2264Sjacobs 	if ((ld != NULL) &&
2448*2264Sjacobs 	    (dn != NULL) && (credp != NULL) && (methodp != NULL))
2449*2264Sjacobs 	{
2450*2264Sjacobs 		if ((freeit == 0) && (sDN != NULL) && (sPasswd != NULL))
2451*2264Sjacobs 		{
2452*2264Sjacobs 			/* first call - get the saved bind credentials */
2453*2264Sjacobs 
2454*2264Sjacobs 			*dn = strdup(sDN);
2455*2264Sjacobs 			*credp = strdup(sPasswd);
2456*2264Sjacobs 			*methodp = sMethod;
2457*2264Sjacobs 		}
2458*2264Sjacobs 		else
2459*2264Sjacobs 		if (freeit == -1)
2460*2264Sjacobs 		{
2461*2264Sjacobs 			/* initial call - save the saved bind credentials */
2462*2264Sjacobs 
2463*2264Sjacobs 			sDN = *dn;
2464*2264Sjacobs 			sPasswd = *credp;
2465*2264Sjacobs 			sMethod = *methodp;
2466*2264Sjacobs 		}
2467*2264Sjacobs 		else
2468*2264Sjacobs 		{
2469*2264Sjacobs 			result = 1;	/* error */
2470*2264Sjacobs 		}
2471*2264Sjacobs 	}
2472*2264Sjacobs 	else
2473*2264Sjacobs 	{
2474*2264Sjacobs 		result = 1;	/* error */
2475*2264Sjacobs 	}
2476*2264Sjacobs 
2477*2264Sjacobs 	return (result);
2478*2264Sjacobs } /* _manageReferralCredentials */
2479