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