10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52830Sdjl * Common Development and Distribution License (the "License").
62830Sdjl * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*8040SBaban.Kenkre@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <pwd.h>
270Sstevel@tonic-gate #include "ldap_common.h"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /* passwd attributes filters */
300Sstevel@tonic-gate #define _PWD_CN "cn"
310Sstevel@tonic-gate #define _PWD_UID "uid"
320Sstevel@tonic-gate #define _PWD_USERPASSWORD "userpassword"
330Sstevel@tonic-gate #define _PWD_UIDNUMBER "uidnumber"
340Sstevel@tonic-gate #define _PWD_GIDNUMBER "gidnumber"
350Sstevel@tonic-gate #define _PWD_GECOS "gecos"
360Sstevel@tonic-gate #define _PWD_DESCRIPTION "description"
370Sstevel@tonic-gate #define _PWD_HOMEDIRECTORY "homedirectory"
380Sstevel@tonic-gate #define _PWD_LOGINSHELL "loginshell"
390Sstevel@tonic-gate
400Sstevel@tonic-gate
410Sstevel@tonic-gate #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))"
420Sstevel@tonic-gate #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))"
430Sstevel@tonic-gate #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%ld))"
440Sstevel@tonic-gate #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%ld))"
450Sstevel@tonic-gate
460Sstevel@tonic-gate static const char *pwd_attrs[] = {
470Sstevel@tonic-gate _PWD_CN,
480Sstevel@tonic-gate _PWD_UID,
490Sstevel@tonic-gate _PWD_UIDNUMBER,
500Sstevel@tonic-gate _PWD_GIDNUMBER,
510Sstevel@tonic-gate _PWD_GECOS,
520Sstevel@tonic-gate _PWD_DESCRIPTION,
530Sstevel@tonic-gate _PWD_HOMEDIRECTORY,
540Sstevel@tonic-gate _PWD_LOGINSHELL,
550Sstevel@tonic-gate (char *)NULL
560Sstevel@tonic-gate };
570Sstevel@tonic-gate
580Sstevel@tonic-gate /*
592830Sdjl * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY
600Sstevel@tonic-gate * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
610Sstevel@tonic-gate * called after a successful ldap search has been performed. This method will
622830Sdjl * parse the ldap search values into the file format.
632830Sdjl * e.g.
642830Sdjl *
652830Sdjl * nobody:x:60001:60001:Nobody:/:
662830Sdjl *
670Sstevel@tonic-gate */
680Sstevel@tonic-gate static int
_nss_ldap_passwd2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)692830Sdjl _nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate int nss_result;
722830Sdjl int buflen = 0;
732830Sdjl unsigned long str_len = 0L;
742830Sdjl char *buffer = NULL;
750Sstevel@tonic-gate ns_ldap_result_t *result = be->result;
762830Sdjl ns_ldap_entry_t *entry;
772830Sdjl char **uid_v, **uidn_v, **gidn_v;
782830Sdjl char **gecos_v, **homedir_v, **shell_v;
792830Sdjl char *NULL_STR = "";
80*8040SBaban.Kenkre@Sun.COM char uid_nobody[NOBODY_STR_LEN];
81*8040SBaban.Kenkre@Sun.COM char gid_nobody[NOBODY_STR_LEN], *end;
82*8040SBaban.Kenkre@Sun.COM char *uid_nobody_v[1], *gid_nobody_v[1];
83*8040SBaban.Kenkre@Sun.COM
84*8040SBaban.Kenkre@Sun.COM (void) snprintf(uid_nobody, sizeof (uid_nobody), "%u", UID_NOBODY);
85*8040SBaban.Kenkre@Sun.COM uid_nobody_v[0] = uid_nobody;
86*8040SBaban.Kenkre@Sun.COM (void) snprintf(gid_nobody, sizeof (gid_nobody), "%u", GID_NOBODY);
87*8040SBaban.Kenkre@Sun.COM gid_nobody_v[0] = gid_nobody;
880Sstevel@tonic-gate
892830Sdjl if (result == NULL)
902830Sdjl return (NSS_STR_PARSE_PARSE);
910Sstevel@tonic-gate
922830Sdjl entry = result->entry;
932830Sdjl
942830Sdjl buflen = argp->buf.buflen;
950Sstevel@tonic-gate buffer = argp->buf.buffer;
960Sstevel@tonic-gate
972830Sdjl nss_result = NSS_STR_PARSE_SUCCESS;
980Sstevel@tonic-gate (void) memset(buffer, 0, buflen);
990Sstevel@tonic-gate
1002830Sdjl /* 8 = 6 ':' + 1 '\0' + 1 'x' */
1012830Sdjl buflen -= 8;
1020Sstevel@tonic-gate
1032830Sdjl uid_v = __ns_ldap_getAttr(entry, _PWD_UID);
1042830Sdjl uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER);
1052830Sdjl gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER);
1062830Sdjl if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL ||
107*8040SBaban.Kenkre@Sun.COM uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) {
1082830Sdjl nss_result = NSS_STR_PARSE_PARSE;
1092830Sdjl goto result_pwd2str;
1102830Sdjl }
111*8040SBaban.Kenkre@Sun.COM /* Validate UID and GID */
112*8040SBaban.Kenkre@Sun.COM if (strtoul(uidn_v[0], &end, 10) > MAXUID)
113*8040SBaban.Kenkre@Sun.COM uidn_v = uid_nobody_v;
114*8040SBaban.Kenkre@Sun.COM if (strtoul(gidn_v[0], &end, 10) > MAXUID)
115*8040SBaban.Kenkre@Sun.COM gidn_v = gid_nobody_v;
1162830Sdjl str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]);
1172830Sdjl if (str_len > buflen) {
1182830Sdjl nss_result = NSS_STR_PARSE_ERANGE;
1192830Sdjl goto result_pwd2str;
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate
1222830Sdjl gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS);
1232830Sdjl if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
1242830Sdjl gecos_v = &NULL_STR;
1252830Sdjl else
1262830Sdjl str_len += strlen(gecos_v[0]);
1270Sstevel@tonic-gate
1282830Sdjl homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY);
1292830Sdjl if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
1302830Sdjl homedir_v = &NULL_STR;
1312830Sdjl else
1322830Sdjl str_len += strlen(homedir_v[0]);
1332830Sdjl
1342830Sdjl shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL);
1352830Sdjl if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
1362830Sdjl shell_v = &NULL_STR;
1372830Sdjl else
1382830Sdjl str_len += strlen(shell_v[0]);
1392830Sdjl
1402830Sdjl if (str_len > buflen) {
1412830Sdjl nss_result = NSS_STR_PARSE_ERANGE;
1422830Sdjl goto result_pwd2str;
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate
1452830Sdjl if (argp->buf.result != NULL) {
1462830Sdjl be->buflen = str_len + 8;
1472830Sdjl be->buffer = malloc(be->buflen);
1482830Sdjl if (be->buffer == NULL) {
1492830Sdjl nss_result = (int)NSS_STR_PARSE_ERANGE;
1502830Sdjl goto result_pwd2str;
1512830Sdjl }
1522830Sdjl
1532830Sdjl (void) snprintf(be->buffer, be->buflen,
154*8040SBaban.Kenkre@Sun.COM "%s:%s:%s:%s:%s:%s:%s",
155*8040SBaban.Kenkre@Sun.COM uid_v[0], "x", uidn_v[0], gidn_v[0],
156*8040SBaban.Kenkre@Sun.COM gecos_v[0], homedir_v[0], shell_v[0]);
1572830Sdjl } else {
1582830Sdjl (void) snprintf(argp->buf.buffer, (str_len + 8),
159*8040SBaban.Kenkre@Sun.COM "%s:%s:%s:%s:%s:%s:%s",
160*8040SBaban.Kenkre@Sun.COM uid_v[0], "x", uidn_v[0], gidn_v[0],
161*8040SBaban.Kenkre@Sun.COM gecos_v[0], homedir_v[0], shell_v[0]);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1642830Sdjl result_pwd2str:
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
1670Sstevel@tonic-gate return ((int)nss_result);
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate * getbyname gets a passwd entry by uid name. This function constructs an ldap
1720Sstevel@tonic-gate * search filter using the name invocation parameter and the getpwnam search
1730Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching
1740Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend
1750Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling.
1760Sstevel@tonic-gate */
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate static nss_status_t
getbyname(ldap_backend_ptr be,void * a)1790Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
1800Sstevel@tonic-gate {
1810Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
1820Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
1830Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
1840Sstevel@tonic-gate char name[SEARCHFILTERLEN];
1850Sstevel@tonic-gate int ret;
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
1880Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name);
1910Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
1920Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name);
1950Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
1960Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp,
199*8040SBaban.Kenkre@Sun.COM _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata));
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate * getbyuid gets a passwd entry by uid number. This function constructs an ldap
2050Sstevel@tonic-gate * search filter using the uid invocation parameter and the getpwuid search
2060Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching
2070Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend
2080Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling.
2090Sstevel@tonic-gate */
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate static nss_status_t
getbyuid(ldap_backend_ptr be,void * a)2120Sstevel@tonic-gate getbyuid(ldap_backend_ptr be, void *a)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2150Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
2160Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
2170Sstevel@tonic-gate int ret;
2180Sstevel@tonic-gate
219*8040SBaban.Kenkre@Sun.COM if (argp->key.uid > MAXUID)
220*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
221*8040SBaban.Kenkre@Sun.COM
2220Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter),
2230Sstevel@tonic-gate _F_GETPWUID, (long)argp->key.uid);
2240Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
2250Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata),
2280Sstevel@tonic-gate _F_GETPWUID_SSD, (long)argp->key.uid);
2290Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
2300Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp,
233*8040SBaban.Kenkre@Sun.COM _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata));
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate static ldap_backend_op_t passwd_ops[] = {
2370Sstevel@tonic-gate _nss_ldap_destr,
2380Sstevel@tonic-gate _nss_ldap_endent,
2390Sstevel@tonic-gate _nss_ldap_setent,
2400Sstevel@tonic-gate _nss_ldap_getent,
2410Sstevel@tonic-gate getbyname,
2420Sstevel@tonic-gate getbyuid
2430Sstevel@tonic-gate };
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * _nss_ldap_passwd_constr is where life begins. This function calls the
2480Sstevel@tonic-gate * generic ldap constructor function to define and build the abstract
2490Sstevel@tonic-gate * data types required to support ldap operations.
2500Sstevel@tonic-gate */
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /*ARGSUSED0*/
2530Sstevel@tonic-gate nss_backend_t *
_nss_ldap_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)2540Sstevel@tonic-gate _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2,
2550Sstevel@tonic-gate const char *dummy3)
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(passwd_ops,
259*8040SBaban.Kenkre@Sun.COM sizeof (passwd_ops)/sizeof (passwd_ops[0]),
260*8040SBaban.Kenkre@Sun.COM _PASSWD, pwd_attrs, _nss_ldap_passwd2str));
2610Sstevel@tonic-gate }
262