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.
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.
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]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include "ldap_common.h"
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/yp_prot.h>
37 /* getent attributes filters */
38 #define _F_GETALIASENT "(objectClass=rfc822MailGroup)"
39 #define _F_GETAUTHNAME "(objectClass=SolarisAuthAttr)"
40 #define _F_GETEXECNAME "(objectClass=SolarisExecAttr)"
41 #define _F_GETGRENT "(objectClass=posixGroup)"
42 #define _F_GETHOSTENT "(objectClass=ipHost)"
43 #define _F_GETNETENT "(objectClass=ipNetwork)"
44 #define _F_GETPROFNAME \
45 "(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))"
46 #define _F_GETPROTOENT "(objectClass=ipProtocol)"
47 #define _F_GETPWENT "(objectClass=posixAccount)"
48 #define _F_GETPRINTERENT "(objectClass=sunPrinter)"
49 #define _F_GETRPCENT "(objectClass=oncRpc)"
50 #define _F_GETSERVENT "(objectClass=ipService)"
51 #define _F_GETSPENT "(objectclass=shadowAccount)"
52 #define _F_GETUSERNAME "(objectClass=SolarisUserAttr)"
53 #define _F_GETPROJENT "(objectClass=SolarisProject)"
54 #define _F_GETENT_SSD "(%s)"
56 /* getent sort attributes */
58 #define _A_GIDNUMBER "gidnumber"
60 #define _A_IPNETWORKNUM "ipnetworknumber"
61 #define _A_PROJECTNAM "SolarisProjectName"
63 static struct gettablefilter
{
67 } gettablefilterent
[] = {
68 {(char *)_PASSWD
, (char *)_F_GETPWENT
, (char *)_A_UID
},
69 {(char *)_SHADOW
, (char *)_F_GETSPENT
, (char *)_A_UID
},
70 {(char *)_GROUP
, (char *)_F_GETGRENT
, (char *)_A_GIDNUMBER
},
71 {(char *)_HOSTS
, (char *)_F_GETHOSTENT
, (char *)_A_CN
},
72 {(char *)_NETWORKS
, (char *)_F_GETNETENT
,
73 (char *)_A_IPNETWORKNUM
},
74 {(char *)_PROTOCOLS
, (char *)_F_GETPROTOENT
, (char *)_A_CN
},
75 {(char *)_RPC
, (char *)_F_GETRPCENT
, (char *)_A_CN
},
76 {(char *)_ALIASES
, (char *)_F_GETALIASENT
, (char *)_A_CN
},
77 {(char *)_SERVICES
, (char *)_F_GETSERVENT
, (char *)_A_CN
},
78 {(char *)_AUTHATTR
, (char *)_F_GETAUTHNAME
, (char *)_A_CN
},
79 {(char *)_EXECATTR
, (char *)_F_GETEXECNAME
, (char *)_A_CN
},
80 {(char *)_PROFATTR
, (char *)_F_GETPROFNAME
, (char *)_A_CN
},
81 {(char *)_USERATTR
, (char *)_F_GETUSERNAME
, (char *)_A_UID
},
82 {(char *)_PROJECT
, (char *)_F_GETPROJENT
, (char *)_A_PROJECTNAM
},
83 {(char *)_PRINTERS
, (char *)_F_GETPRINTERENT
, (char *)_A_CN
},
89 switch_err(int rc
, ns_ldap_error_t
*error
)
95 case NS_LDAP_NOTFOUND
:
96 return (NSS_NOTFOUND
);
99 return (NSS_TRYAGAIN
);
101 case NS_LDAP_INTERNAL
:
102 if (error
&& (error
->status
== LDAP_SERVER_DOWN
||
103 error
->status
== LDAP_TIMEOUT
))
104 return (NSS_TRYAGAIN
);
106 return (NSS_UNAVAIL
);
109 return (NSS_UNAVAIL
);
114 _nss_ldap_lookup(ldap_backend_ptr be
, nss_XbyY_args_t
*argp
,
115 char *database
, char *searchfilter
, char *domain
,
116 int (*init_filter_cb
)(const ns_ldap_search_desc_t
*desc
,
117 char **realfilter
, const void *userdata
),
118 const void *userdata
)
120 int callbackstat
= 0;
121 ns_ldap_error_t
*error
= NULL
;
125 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_lookup]\n");
126 (void) fprintf(stdout
, "\tsearchfilter: %s\n", searchfilter
);
127 (void) fprintf(stdout
,
128 "\tuserdata: %s\n", userdata
? userdata
: "NULL");
129 (void) fprintf(stdout
, "\tdatabase: %s\n", database
);
132 (void) __ns_ldap_freeResult(&be
->result
);
134 if ((rc
= __ns_ldap_list(database
, searchfilter
, init_filter_cb
,
135 be
->attrs
, NULL
, 0, &be
->result
, &error
, NULL
,
136 userdata
)) != NS_LDAP_SUCCESS
) {
138 rc
= switch_err(rc
, error
);
139 (void) __ns_ldap_freeError(&error
);
143 (void) __ns_ldap_freeError(&error
);
144 /* callback function */
146 be
->ldapobj2str(be
, argp
)) != NSS_STR_PARSE_SUCCESS
) {
151 * publickey does not have a front end marshaller and expects
152 * a string to be returned in NSS.
153 * No need to convert file format -> struct.
156 if (be
->db_type
== NSS_LDAP_DB_PUBLICKEY
) {
157 argp
->returnval
= argp
->buf
.buffer
;
158 argp
->returnlen
= strlen(argp
->buf
.buffer
);
159 be
->db_type
= NSS_LDAP_DB_NONE
;
160 return (NSS_SUCCESS
);
163 * Assume the switch engine wants the returned data in the file
164 * format when argp->buf.result == NULL.
165 * The front-end marshaller str2ether(ethers) uses
166 * ent (argp->buf.result) and buffer (argp->buf.buffer)
167 * for different purpose so ethers has to be treated differently.
169 if (argp
->buf
.result
!= NULL
||
170 be
->db_type
== NSS_LDAP_DB_ETHERS
) {
171 /* file format -> struct */
172 if (argp
->str2ent
== NULL
) {
173 callbackstat
= NSS_STR_PARSE_PARSE
;
177 callbackstat
= (*argp
->str2ent
)(be
->buffer
,
182 if (callbackstat
== NSS_STR_PARSE_SUCCESS
) {
183 if (be
->db_type
== NSS_LDAP_DB_ETHERS
&&
184 argp
->buf
.buffer
!= NULL
) {
185 argp
->returnval
= argp
->buf
.buffer
;
186 argp
->returnlen
= strlen(argp
->buf
.buffer
);
188 argp
->returnval
= argp
->buf
.result
;
189 argp
->returnlen
= 1; /* irrelevant */
191 if (be
->buffer
!= NULL
) {
195 be
->db_type
= NSS_LDAP_DB_NONE
;
197 return ((nss_status_t
)NSS_SUCCESS
);
200 /* return file format in argp->buf.buffer */
201 argp
->returnval
= argp
->buf
.buffer
;
202 argp
->returnlen
= strlen(argp
->buf
.buffer
);
203 return ((nss_status_t
)NSS_SUCCESS
);
207 if (be
->buffer
!= NULL
) {
211 be
->db_type
= NSS_LDAP_DB_NONE
;
214 if (callbackstat
== NSS_STR_PARSE_PARSE
) {
216 return ((nss_status_t
)NSS_NOTFOUND
);
218 if (callbackstat
== NSS_STR_PARSE_ERANGE
) {
220 return ((nss_status_t
)NSS_NOTFOUND
);
222 if (callbackstat
== NSS_STR_PARSE_NO_ADDR
) {
223 /* No IPV4 address is found */
224 argp
->h_errno
= HOST_NOT_FOUND
;
225 return ((nss_status_t
)NSS_NOTFOUND
);
227 return ((nss_status_t
)NSS_UNAVAIL
);
231 * This function is similar to _nss_ldap_lookup except it does not
232 * do a callback. It is only used by getnetgrent.c
237 _nss_ldap_nocb_lookup(ldap_backend_ptr be
, nss_XbyY_args_t
*argp
,
238 char *database
, char *searchfilter
, char *domain
,
239 int (*init_filter_cb
)(const ns_ldap_search_desc_t
*desc
,
240 char **realfilter
, const void *userdata
),
241 const void *userdata
)
243 ns_ldap_error_t
*error
= NULL
;
247 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
248 (void) fprintf(stdout
, "\tsearchfilter: %s\n", searchfilter
);
249 (void) fprintf(stdout
, "\tdatabase: %s\n", database
);
250 (void) fprintf(stdout
,
251 "\tuserdata: %s\n", userdata
? userdata
: "NULL");
254 (void) __ns_ldap_freeResult(&be
->result
);
256 if ((rc
= __ns_ldap_list(database
, searchfilter
, init_filter_cb
,
257 be
->attrs
, NULL
, 0, &be
->result
, &error
, NULL
,
258 userdata
)) != NS_LDAP_SUCCESS
) {
261 rc
= switch_err(rc
, error
);
262 (void) __ns_ldap_freeError(&error
);
266 return ((nss_status_t
)NSS_SUCCESS
);
275 _clean_ldap_backend(ldap_backend_ptr be
)
277 ns_ldap_error_t
*error
;
280 (void) fprintf(stdout
, "\n[ldap_common.c: _clean_ldap_backend]\n");
284 if (be
->result
!= NULL
)
285 (void) __ns_ldap_freeResult(&be
->result
);
286 if (be
->enumcookie
!= NULL
)
287 (void) __ns_ldap_endEntry(&be
->enumcookie
, &error
);
288 if (be
->services_cookie
!= NULL
)
289 _nss_services_cookie_free((void **)&be
->services_cookie
);
290 if (be
->toglue
!= NULL
) {
294 if (be
->buffer
!= NULL
) {
303 * _nss_ldap_destr will free all smalloc'ed variable strings and structures
304 * before exiting this nsswitch shared backend library. This function is
305 * called before returning control back to nsswitch.
310 _nss_ldap_destr(ldap_backend_ptr be
, void *a
)
314 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_destr]\n");
317 (void) _clean_ldap_backend(be
);
319 return ((nss_status_t
)NSS_SUCCESS
);
324 * _nss_ldap_setent called before _nss_ldap_getent. This function is
329 _nss_ldap_setent(ldap_backend_ptr be
, void *a
)
331 struct gettablefilter
*gtf
;
334 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_setent]\n");
337 if (be
->setcalled
== 1)
338 (void) _nss_ldap_endent(be
, a
);
341 for (gtf
= gettablefilterent
; gtf
->tablename
!= NULL
; gtf
++) {
342 if (strcmp(gtf
->tablename
, be
->tablename
))
344 be
->filter
= (char *)gtf
->tablefilter
;
345 be
->sortattr
= (char *)gtf
->sortattr
;
350 be
->enumcookie
= NULL
;
352 be
->services_cookie
= NULL
;
354 return ((nss_status_t
)NSS_SUCCESS
);
359 * _nss_ldap_endent called after _nss_ldap_getent. This function is
365 _nss_ldap_endent(ldap_backend_ptr be
, void *a
)
367 ns_ldap_error_t
*error
= NULL
;
370 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_endent]\n");
376 if (be
->enumcookie
!= NULL
) {
377 (void) __ns_ldap_endEntry(&be
->enumcookie
, &error
);
378 (void) __ns_ldap_freeError(&error
);
380 if (be
->result
!= NULL
) {
381 (void) __ns_ldap_freeResult(&be
->result
);
383 if (be
->services_cookie
!= NULL
) {
384 _nss_services_cookie_free((void **)&be
->services_cookie
);
386 if (be
->buffer
!= NULL
) {
391 return ((nss_status_t
)NSS_SUCCESS
);
400 _nss_ldap_getent(ldap_backend_ptr be
, void *a
)
402 nss_XbyY_args_t
*argp
= (nss_XbyY_args_t
*)a
;
403 ns_ldap_error_t
*error
= NULL
;
408 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_getent]\n");
411 if (be
->setcalled
== 0)
412 (void) _nss_ldap_setent(be
, a
);
415 if (be
->enumcookie
== NULL
) {
416 retcode
= __ns_ldap_firstEntry(be
->tablename
,
417 be
->filter
, be
->sortattr
, _merge_SSD_filter
, be
->attrs
,
418 NULL
, 0, &be
->enumcookie
,
419 &be
->result
, &error
, _F_GETENT_SSD
);
421 if (be
->services_cookie
== NULL
) {
422 retcode
= __ns_ldap_nextEntry(be
->enumcookie
,
423 &be
->result
, &error
);
426 if (retcode
!= NS_LDAP_SUCCESS
) {
427 retcode
= switch_err(retcode
, error
);
428 (void) __ns_ldap_freeError(&error
);
429 (void) _nss_ldap_endent(be
, a
);
433 if (be
->result
== NULL
) {
434 parsestat
= NSS_STR_PARSE_NO_RESULT
;
437 /* ns_ldap_entry_t -> file format */
438 if ((parsestat
= be
->ldapobj2str(be
, argp
))
439 == NSS_STR_PARSE_SUCCESS
) {
440 if (argp
->buf
.result
!= NULL
) {
441 /* file format -> struct */
442 if (argp
->str2ent
== NULL
) {
443 parsestat
= NSS_STR_PARSE_NO_RESULT
;
446 parsestat
= (*argp
->str2ent
)(be
->buffer
,
451 if (parsestat
== NSS_STR_PARSE_SUCCESS
) {
452 if (be
->buffer
!= NULL
) {
458 argp
->returnval
= argp
->buf
.result
;
459 argp
->returnlen
= 1; /* irrevelant */
460 return ((nss_status_t
)NSS_SUCCESS
);
464 * nscd is not caching the enumerated
465 * entries. This code path would be dormant.
466 * Keep this path for the future references.
468 argp
->returnval
= argp
->buf
.buffer
;
470 strlen(argp
->buf
.buffer
) + 1;
474 if (be
->buffer
!= NULL
) {
480 if (parsestat
== NSS_STR_PARSE_NO_RESULT
) {
482 (void) _nss_ldap_endent(be
, a
);
483 return ((nss_status_t
)NSS_NOTFOUND
);
486 if (parsestat
== NSS_STR_PARSE_ERANGE
) {
488 (void) _nss_ldap_endent(be
, a
);
489 return ((nss_status_t
)NSS_NOTFOUND
);
491 if (parsestat
== NSS_STR_PARSE_NO_ADDR
)
493 * No IPV4 address is found in the current entry.
494 * It indicates that the entry contains IPV6 addresses
495 * only. Instead of calling _nss_ldap_endent to
496 * terminate, get next entry to continue enumeration.
497 * If it returned NSS_NOTFOUND here,
498 * gethostent() would return NULL
499 * and the enumeration would stop prematurely.
503 if (parsestat
== NSS_STR_PARSE_PARSE
)
505 * There has been a parse error. Most likely some
506 * mandatory attributes are missing. Ignore the error
507 * and get the next entry. If we returned an error the
508 * enumeration would stop prematurely.
512 return ((nss_status_t
)NSS_SUCCESS
);
521 _nss_ldap_constr(ldap_backend_op_t ops
[], int nops
, char *tablename
,
522 const char **attrs
, fnf ldapobj2str
)
527 (void) fprintf(stdout
, "\n[ldap_common.c: _nss_ldap_constr]\n");
530 if ((be
= (ldap_backend_ptr
) calloc(1, sizeof (*be
))) == 0)
533 be
->nops
= (nss_dbop_t
)nops
;
534 be
->tablename
= (char *)strdup(tablename
);
536 be
->ldapobj2str
= ldapobj2str
;
538 return ((nss_backend_t
*)be
);
546 chophostdomain(char *string
, char *host
, char *domain
)
553 if ((dot
= strchr(string
, '.')) == NULL
) {
557 (void) strcpy(host
, string
);
558 (void) strcpy(domain
, ++dot
);
568 propersubdomain(char *domain
, char *subdomain
)
570 int domainlen
, subdomainlen
;
573 if (domain
== NULL
|| subdomain
== NULL
)
576 domainlen
= strlen(domain
);
577 subdomainlen
= strlen(subdomain
);
579 /* is afterdot a substring of domain? */
580 if ((strncasecmp(domain
, subdomain
, subdomainlen
)) != 0)
583 if (domainlen
== subdomainlen
)
586 if (subdomainlen
> domainlen
)
589 if (*(domain
+ subdomainlen
) != '.')