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