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 5*2830Sdjl * Common Development and Distribution License (the "License"). 6*2830Sdjl * 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*2830Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <pwd.h> 290Sstevel@tonic-gate #include "ldap_common.h" 300Sstevel@tonic-gate 310Sstevel@tonic-gate /* passwd attributes filters */ 320Sstevel@tonic-gate #define _PWD_CN "cn" 330Sstevel@tonic-gate #define _PWD_UID "uid" 340Sstevel@tonic-gate #define _PWD_USERPASSWORD "userpassword" 350Sstevel@tonic-gate #define _PWD_UIDNUMBER "uidnumber" 360Sstevel@tonic-gate #define _PWD_GIDNUMBER "gidnumber" 370Sstevel@tonic-gate #define _PWD_GECOS "gecos" 380Sstevel@tonic-gate #define _PWD_DESCRIPTION "description" 390Sstevel@tonic-gate #define _PWD_HOMEDIRECTORY "homedirectory" 400Sstevel@tonic-gate #define _PWD_LOGINSHELL "loginshell" 410Sstevel@tonic-gate 420Sstevel@tonic-gate 430Sstevel@tonic-gate #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))" 440Sstevel@tonic-gate #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))" 450Sstevel@tonic-gate #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%ld))" 460Sstevel@tonic-gate #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%ld))" 470Sstevel@tonic-gate 480Sstevel@tonic-gate static const char *pwd_attrs[] = { 490Sstevel@tonic-gate _PWD_CN, 500Sstevel@tonic-gate _PWD_UID, 510Sstevel@tonic-gate _PWD_UIDNUMBER, 520Sstevel@tonic-gate _PWD_GIDNUMBER, 530Sstevel@tonic-gate _PWD_GECOS, 540Sstevel@tonic-gate _PWD_DESCRIPTION, 550Sstevel@tonic-gate _PWD_HOMEDIRECTORY, 560Sstevel@tonic-gate _PWD_LOGINSHELL, 570Sstevel@tonic-gate (char *)NULL 580Sstevel@tonic-gate }; 590Sstevel@tonic-gate 600Sstevel@tonic-gate /* 61*2830Sdjl * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY 620Sstevel@tonic-gate * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is 630Sstevel@tonic-gate * called after a successful ldap search has been performed. This method will 64*2830Sdjl * parse the ldap search values into the file format. 65*2830Sdjl * e.g. 66*2830Sdjl * 67*2830Sdjl * nobody:x:60001:60001:Nobody:/: 68*2830Sdjl * 690Sstevel@tonic-gate */ 700Sstevel@tonic-gate static int 71*2830Sdjl _nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) 720Sstevel@tonic-gate { 730Sstevel@tonic-gate int nss_result; 74*2830Sdjl int buflen = 0; 75*2830Sdjl unsigned long str_len = 0L; 76*2830Sdjl char *buffer = NULL; 770Sstevel@tonic-gate ns_ldap_result_t *result = be->result; 78*2830Sdjl ns_ldap_entry_t *entry; 79*2830Sdjl char **uid_v, **uidn_v, **gidn_v; 80*2830Sdjl char **gecos_v, **homedir_v, **shell_v; 81*2830Sdjl char *NULL_STR = ""; 820Sstevel@tonic-gate 83*2830Sdjl if (result == NULL) 84*2830Sdjl return (NSS_STR_PARSE_PARSE); 850Sstevel@tonic-gate 86*2830Sdjl entry = result->entry; 87*2830Sdjl 88*2830Sdjl buflen = argp->buf.buflen; 890Sstevel@tonic-gate buffer = argp->buf.buffer; 900Sstevel@tonic-gate 91*2830Sdjl nss_result = NSS_STR_PARSE_SUCCESS; 920Sstevel@tonic-gate (void) memset(buffer, 0, buflen); 930Sstevel@tonic-gate 94*2830Sdjl /* 8 = 6 ':' + 1 '\0' + 1 'x' */ 95*2830Sdjl buflen -= 8; 960Sstevel@tonic-gate 97*2830Sdjl uid_v = __ns_ldap_getAttr(entry, _PWD_UID); 98*2830Sdjl uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER); 99*2830Sdjl gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER); 100*2830Sdjl if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL || 101*2830Sdjl uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) { 102*2830Sdjl nss_result = NSS_STR_PARSE_PARSE; 103*2830Sdjl goto result_pwd2str; 104*2830Sdjl } 105*2830Sdjl str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]); 106*2830Sdjl if (str_len > buflen) { 107*2830Sdjl nss_result = NSS_STR_PARSE_ERANGE; 108*2830Sdjl goto result_pwd2str; 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate 111*2830Sdjl gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS); 112*2830Sdjl if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0') 113*2830Sdjl gecos_v = &NULL_STR; 114*2830Sdjl else 115*2830Sdjl str_len += strlen(gecos_v[0]); 1160Sstevel@tonic-gate 117*2830Sdjl homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY); 118*2830Sdjl if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0') 119*2830Sdjl homedir_v = &NULL_STR; 120*2830Sdjl else 121*2830Sdjl str_len += strlen(homedir_v[0]); 122*2830Sdjl 123*2830Sdjl shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL); 124*2830Sdjl if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0') 125*2830Sdjl shell_v = &NULL_STR; 126*2830Sdjl else 127*2830Sdjl str_len += strlen(shell_v[0]); 128*2830Sdjl 129*2830Sdjl if (str_len > buflen) { 130*2830Sdjl nss_result = NSS_STR_PARSE_ERANGE; 131*2830Sdjl goto result_pwd2str; 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 134*2830Sdjl if (argp->buf.result != NULL) { 135*2830Sdjl be->buflen = str_len + 8; 136*2830Sdjl be->buffer = malloc(be->buflen); 137*2830Sdjl if (be->buffer == NULL) { 138*2830Sdjl nss_result = (int)NSS_STR_PARSE_ERANGE; 139*2830Sdjl goto result_pwd2str; 140*2830Sdjl } 141*2830Sdjl 142*2830Sdjl (void) snprintf(be->buffer, be->buflen, 143*2830Sdjl "%s:%s:%s:%s:%s:%s:%s", 144*2830Sdjl uid_v[0], "x", uidn_v[0], gidn_v[0], 145*2830Sdjl gecos_v[0], homedir_v[0], shell_v[0]); 146*2830Sdjl } else { 147*2830Sdjl (void) snprintf(argp->buf.buffer, (str_len + 8), 148*2830Sdjl "%s:%s:%s:%s:%s:%s:%s", 149*2830Sdjl uid_v[0], "x", uidn_v[0], gidn_v[0], 150*2830Sdjl gecos_v[0], homedir_v[0], shell_v[0]); 151*2830Sdjl 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 154*2830Sdjl result_pwd2str: 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 1570Sstevel@tonic-gate return ((int)nss_result); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* 1610Sstevel@tonic-gate * getbyname gets a passwd entry by uid name. This function constructs an ldap 1620Sstevel@tonic-gate * search filter using the name invocation parameter and the getpwnam search 1630Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching 1640Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend 1650Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling. 1660Sstevel@tonic-gate */ 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate static nss_status_t 1690Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a) 1700Sstevel@tonic-gate { 1710Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1720Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN]; 1730Sstevel@tonic-gate char userdata[SEARCHFILTERLEN]; 1740Sstevel@tonic-gate char name[SEARCHFILTERLEN]; 1750Sstevel@tonic-gate int ret; 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 1780Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name); 1810Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0) 1820Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name); 1850Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0) 1860Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp, 1890Sstevel@tonic-gate _PASSWD, searchfilter, NULL, 1900Sstevel@tonic-gate _merge_SSD_filter, userdata)); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* 1950Sstevel@tonic-gate * getbyuid gets a passwd entry by uid number. This function constructs an ldap 1960Sstevel@tonic-gate * search filter using the uid invocation parameter and the getpwuid search 1970Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching 1980Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend 1990Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling. 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate static nss_status_t 2030Sstevel@tonic-gate getbyuid(ldap_backend_ptr be, void *a) 2040Sstevel@tonic-gate { 2050Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2060Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN]; 2070Sstevel@tonic-gate char userdata[SEARCHFILTERLEN]; 2080Sstevel@tonic-gate int ret; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), 2110Sstevel@tonic-gate _F_GETPWUID, (long)argp->key.uid); 2120Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0) 2130Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), 2160Sstevel@tonic-gate _F_GETPWUID_SSD, (long)argp->key.uid); 2170Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0) 2180Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp, 2210Sstevel@tonic-gate _PASSWD, searchfilter, NULL, 2220Sstevel@tonic-gate _merge_SSD_filter, userdata)); 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate static ldap_backend_op_t passwd_ops[] = { 2260Sstevel@tonic-gate _nss_ldap_destr, 2270Sstevel@tonic-gate _nss_ldap_endent, 2280Sstevel@tonic-gate _nss_ldap_setent, 2290Sstevel@tonic-gate _nss_ldap_getent, 2300Sstevel@tonic-gate getbyname, 2310Sstevel@tonic-gate getbyuid 2320Sstevel@tonic-gate }; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* 2360Sstevel@tonic-gate * _nss_ldap_passwd_constr is where life begins. This function calls the 2370Sstevel@tonic-gate * generic ldap constructor function to define and build the abstract 2380Sstevel@tonic-gate * data types required to support ldap operations. 2390Sstevel@tonic-gate */ 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate /*ARGSUSED0*/ 2420Sstevel@tonic-gate nss_backend_t * 2430Sstevel@tonic-gate _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2, 2440Sstevel@tonic-gate const char *dummy3) 2450Sstevel@tonic-gate { 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(passwd_ops, 2480Sstevel@tonic-gate sizeof (passwd_ops)/sizeof (passwd_ops[0]), 249*2830Sdjl _PASSWD, pwd_attrs, _nss_ldap_passwd2str)); 2500Sstevel@tonic-gate } 251