1*8040SBaban.Kenkre@Sun.COM /* 2*8040SBaban.Kenkre@Sun.COM * CDDL HEADER START 3*8040SBaban.Kenkre@Sun.COM * 4*8040SBaban.Kenkre@Sun.COM * The contents of this file are subject to the terms of the 5*8040SBaban.Kenkre@Sun.COM * Common Development and Distribution License (the "License"). 6*8040SBaban.Kenkre@Sun.COM * You may not use this file except in compliance with the License. 7*8040SBaban.Kenkre@Sun.COM * 8*8040SBaban.Kenkre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*8040SBaban.Kenkre@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*8040SBaban.Kenkre@Sun.COM * See the License for the specific language governing permissions 11*8040SBaban.Kenkre@Sun.COM * and limitations under the License. 12*8040SBaban.Kenkre@Sun.COM * 13*8040SBaban.Kenkre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*8040SBaban.Kenkre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*8040SBaban.Kenkre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*8040SBaban.Kenkre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*8040SBaban.Kenkre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*8040SBaban.Kenkre@Sun.COM * 19*8040SBaban.Kenkre@Sun.COM * CDDL HEADER END 20*8040SBaban.Kenkre@Sun.COM */ 21*8040SBaban.Kenkre@Sun.COM /* 22*8040SBaban.Kenkre@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*8040SBaban.Kenkre@Sun.COM * Use is subject to license terms. 24*8040SBaban.Kenkre@Sun.COM */ 25*8040SBaban.Kenkre@Sun.COM 26*8040SBaban.Kenkre@Sun.COM #include <pwd.h> 27*8040SBaban.Kenkre@Sun.COM #include <idmap.h> 28*8040SBaban.Kenkre@Sun.COM #include <ctype.h> 29*8040SBaban.Kenkre@Sun.COM #include "ad_common.h" 30*8040SBaban.Kenkre@Sun.COM 31*8040SBaban.Kenkre@Sun.COM /* passwd attributes and filters */ 32*8040SBaban.Kenkre@Sun.COM #define _PWD_DN "dn" 33*8040SBaban.Kenkre@Sun.COM #define _PWD_SAN "sAMAccountName" 34*8040SBaban.Kenkre@Sun.COM #define _PWD_OBJSID "objectSid" 35*8040SBaban.Kenkre@Sun.COM #define _PWD_PRIMARYGROUPID "primaryGroupID" 36*8040SBaban.Kenkre@Sun.COM #define _PWD_CN "cn" 37*8040SBaban.Kenkre@Sun.COM #define _PWD_HOMEDIRECTORY "homedirectory" 38*8040SBaban.Kenkre@Sun.COM #define _PWD_LOGINSHELL "loginshell" 39*8040SBaban.Kenkre@Sun.COM #define _PWD_OBJCLASS "objectClass" 40*8040SBaban.Kenkre@Sun.COM 41*8040SBaban.Kenkre@Sun.COM #define _F_GETPWNAM "(sAMAccountName=%.*s)" 42*8040SBaban.Kenkre@Sun.COM #define _F_GETPWUID "(objectSid=%s)" 43*8040SBaban.Kenkre@Sun.COM 44*8040SBaban.Kenkre@Sun.COM static const char *pwd_attrs[] = { 45*8040SBaban.Kenkre@Sun.COM _PWD_SAN, 46*8040SBaban.Kenkre@Sun.COM _PWD_OBJSID, 47*8040SBaban.Kenkre@Sun.COM _PWD_PRIMARYGROUPID, 48*8040SBaban.Kenkre@Sun.COM _PWD_CN, 49*8040SBaban.Kenkre@Sun.COM _PWD_HOMEDIRECTORY, 50*8040SBaban.Kenkre@Sun.COM _PWD_LOGINSHELL, 51*8040SBaban.Kenkre@Sun.COM _PWD_OBJCLASS, 52*8040SBaban.Kenkre@Sun.COM (char *)NULL 53*8040SBaban.Kenkre@Sun.COM }; 54*8040SBaban.Kenkre@Sun.COM 55*8040SBaban.Kenkre@Sun.COM static int 56*8040SBaban.Kenkre@Sun.COM update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp, 57*8040SBaban.Kenkre@Sun.COM const char *name, const char *domain, 58*8040SBaban.Kenkre@Sun.COM uid_t uid, gid_t gid, const char *gecos, 59*8040SBaban.Kenkre@Sun.COM const char *homedir, const char *shell) 60*8040SBaban.Kenkre@Sun.COM { 61*8040SBaban.Kenkre@Sun.COM int buflen; 62*8040SBaban.Kenkre@Sun.COM char *buffer; 63*8040SBaban.Kenkre@Sun.COM 64*8040SBaban.Kenkre@Sun.COM if (be->db_type == NSS_AD_DB_PASSWD_BYNAME) { 65*8040SBaban.Kenkre@Sun.COM /* 66*8040SBaban.Kenkre@Sun.COM * The canonical name obtained from AD lookup may not match 67*8040SBaban.Kenkre@Sun.COM * the case of the name (i.e. key) in the request. Therefore, 68*8040SBaban.Kenkre@Sun.COM * use the name from the request to construct the result. 69*8040SBaban.Kenkre@Sun.COM */ 70*8040SBaban.Kenkre@Sun.COM buflen = snprintf(NULL, 0, "%s:%s:%u:%u:%s:%s:%s", 71*8040SBaban.Kenkre@Sun.COM argp->key.name, "x", uid, gid, gecos, homedir, shell) + 1; 72*8040SBaban.Kenkre@Sun.COM } else { 73*8040SBaban.Kenkre@Sun.COM if (domain == NULL) 74*8040SBaban.Kenkre@Sun.COM domain = WK_DOMAIN; 75*8040SBaban.Kenkre@Sun.COM buflen = snprintf(NULL, 0, "%s@%s:%s:%u:%u:%s:%s:%s", 76*8040SBaban.Kenkre@Sun.COM name, domain, "x", uid, gid, gecos, homedir, shell) + 1; 77*8040SBaban.Kenkre@Sun.COM } 78*8040SBaban.Kenkre@Sun.COM 79*8040SBaban.Kenkre@Sun.COM 80*8040SBaban.Kenkre@Sun.COM if (argp->buf.result != NULL) { 81*8040SBaban.Kenkre@Sun.COM buffer = be->buffer = malloc(buflen); 82*8040SBaban.Kenkre@Sun.COM if (be->buffer == NULL) 83*8040SBaban.Kenkre@Sun.COM return (-1); 84*8040SBaban.Kenkre@Sun.COM be->buflen = buflen; 85*8040SBaban.Kenkre@Sun.COM } else { 86*8040SBaban.Kenkre@Sun.COM if (buflen > argp->buf.buflen) 87*8040SBaban.Kenkre@Sun.COM return (-1); 88*8040SBaban.Kenkre@Sun.COM buflen = argp->buf.buflen; 89*8040SBaban.Kenkre@Sun.COM buffer = argp->buf.buffer; 90*8040SBaban.Kenkre@Sun.COM } 91*8040SBaban.Kenkre@Sun.COM 92*8040SBaban.Kenkre@Sun.COM if (be->db_type == NSS_AD_DB_PASSWD_BYNAME) 93*8040SBaban.Kenkre@Sun.COM (void) snprintf(buffer, buflen, "%s:%s:%u:%u:%s:%s:%s", 94*8040SBaban.Kenkre@Sun.COM argp->key.name, "x", uid, gid, gecos, homedir, shell); 95*8040SBaban.Kenkre@Sun.COM else 96*8040SBaban.Kenkre@Sun.COM (void) snprintf(buffer, buflen, "%s@%s:%s:%u:%u:%s:%s:%s", 97*8040SBaban.Kenkre@Sun.COM name, domain, "x", uid, gid, gecos, homedir, shell); 98*8040SBaban.Kenkre@Sun.COM return (0); 99*8040SBaban.Kenkre@Sun.COM } 100*8040SBaban.Kenkre@Sun.COM 101*8040SBaban.Kenkre@Sun.COM 102*8040SBaban.Kenkre@Sun.COM #define NET_SCHEME "/net" 103*8040SBaban.Kenkre@Sun.COM 104*8040SBaban.Kenkre@Sun.COM /* 105*8040SBaban.Kenkre@Sun.COM * 1) If the homeDirectory string is in UNC format then convert it into 106*8040SBaban.Kenkre@Sun.COM * a /net format. This needs to be revisited later but is fine for now 107*8040SBaban.Kenkre@Sun.COM * because Solaris does not support -hosts automount map for CIFS yet. 108*8040SBaban.Kenkre@Sun.COM * 109*8040SBaban.Kenkre@Sun.COM * 2) If homeDirectory contains ':' then return NULL because ':' is the 110*8040SBaban.Kenkre@Sun.COM * delimiter in passwd entries and may break apps that parse these entries. 111*8040SBaban.Kenkre@Sun.COM * 112*8040SBaban.Kenkre@Sun.COM * 3) For all other cases return the same string that was passed to 113*8040SBaban.Kenkre@Sun.COM * this function. 114*8040SBaban.Kenkre@Sun.COM */ 115*8040SBaban.Kenkre@Sun.COM static 116*8040SBaban.Kenkre@Sun.COM char * 117*8040SBaban.Kenkre@Sun.COM process_homedir(char *homedir) 118*8040SBaban.Kenkre@Sun.COM { 119*8040SBaban.Kenkre@Sun.COM size_t len, smb_len; 120*8040SBaban.Kenkre@Sun.COM char *smb_homedir; 121*8040SBaban.Kenkre@Sun.COM int i, slash = 0; 122*8040SBaban.Kenkre@Sun.COM 123*8040SBaban.Kenkre@Sun.COM len = strlen(homedir); 124*8040SBaban.Kenkre@Sun.COM 125*8040SBaban.Kenkre@Sun.COM if (strchr(homedir, ':') != NULL) 126*8040SBaban.Kenkre@Sun.COM /* 127*8040SBaban.Kenkre@Sun.COM * Ignore paths that have colon ':' because ':' is a 128*8040SBaban.Kenkre@Sun.COM * delimiter for the passwd entry. 129*8040SBaban.Kenkre@Sun.COM */ 130*8040SBaban.Kenkre@Sun.COM return (NULL); 131*8040SBaban.Kenkre@Sun.COM 132*8040SBaban.Kenkre@Sun.COM if (!(len > 1 && homedir[0] == '\\' && homedir[1] == '\\')) 133*8040SBaban.Kenkre@Sun.COM /* Keep homedir intact if not in UNC format */ 134*8040SBaban.Kenkre@Sun.COM return (homedir); 135*8040SBaban.Kenkre@Sun.COM 136*8040SBaban.Kenkre@Sun.COM /* 137*8040SBaban.Kenkre@Sun.COM * Convert UNC string into /net format 138*8040SBaban.Kenkre@Sun.COM * Example: \\server\abc -> /net/server/abc 139*8040SBaban.Kenkre@Sun.COM */ 140*8040SBaban.Kenkre@Sun.COM smb_len = len + 1 + sizeof (NET_SCHEME); 141*8040SBaban.Kenkre@Sun.COM if ((smb_homedir = calloc(1, smb_len)) == NULL) 142*8040SBaban.Kenkre@Sun.COM return (NULL); 143*8040SBaban.Kenkre@Sun.COM (void) strlcpy(smb_homedir, NET_SCHEME, smb_len); 144*8040SBaban.Kenkre@Sun.COM for (i = strlen(smb_homedir); *homedir != '\0'; homedir++) { 145*8040SBaban.Kenkre@Sun.COM if (*homedir == '\\') { 146*8040SBaban.Kenkre@Sun.COM /* Reduce double backslashes into one */ 147*8040SBaban.Kenkre@Sun.COM if (slash) 148*8040SBaban.Kenkre@Sun.COM slash = 0; 149*8040SBaban.Kenkre@Sun.COM else { 150*8040SBaban.Kenkre@Sun.COM slash = 1; 151*8040SBaban.Kenkre@Sun.COM smb_homedir[i++] = '/'; 152*8040SBaban.Kenkre@Sun.COM } 153*8040SBaban.Kenkre@Sun.COM } else { 154*8040SBaban.Kenkre@Sun.COM smb_homedir[i++] = *homedir; 155*8040SBaban.Kenkre@Sun.COM slash = 0; 156*8040SBaban.Kenkre@Sun.COM } 157*8040SBaban.Kenkre@Sun.COM } 158*8040SBaban.Kenkre@Sun.COM return (smb_homedir); 159*8040SBaban.Kenkre@Sun.COM } 160*8040SBaban.Kenkre@Sun.COM 161*8040SBaban.Kenkre@Sun.COM /* 162*8040SBaban.Kenkre@Sun.COM * _nss_ad_passwd2str is the data marshaling method for the passwd getXbyY 163*8040SBaban.Kenkre@Sun.COM * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is 164*8040SBaban.Kenkre@Sun.COM * called after a successful AD search has been performed. This method will 165*8040SBaban.Kenkre@Sun.COM * parse the AD search values into the file format. 166*8040SBaban.Kenkre@Sun.COM * e.g. 167*8040SBaban.Kenkre@Sun.COM * 168*8040SBaban.Kenkre@Sun.COM * blue@whale:x:123456:10:Blue Whale:/: 169*8040SBaban.Kenkre@Sun.COM * 170*8040SBaban.Kenkre@Sun.COM */ 171*8040SBaban.Kenkre@Sun.COM static int 172*8040SBaban.Kenkre@Sun.COM _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp) 173*8040SBaban.Kenkre@Sun.COM { 174*8040SBaban.Kenkre@Sun.COM int nss_result; 175*8040SBaban.Kenkre@Sun.COM adutils_result_t *result = be->result; 176*8040SBaban.Kenkre@Sun.COM const adutils_entry_t *entry; 177*8040SBaban.Kenkre@Sun.COM char **sid_v, *ptr, **pgid_v, *end; 178*8040SBaban.Kenkre@Sun.COM ulong_t tmp; 179*8040SBaban.Kenkre@Sun.COM uint32_t urid, grid; 180*8040SBaban.Kenkre@Sun.COM uid_t uid; 181*8040SBaban.Kenkre@Sun.COM gid_t gid; 182*8040SBaban.Kenkre@Sun.COM idmap_stat gstat; 183*8040SBaban.Kenkre@Sun.COM idmap_get_handle_t *ig = NULL; 184*8040SBaban.Kenkre@Sun.COM char **name_v, **dn_v, *domain = NULL; 185*8040SBaban.Kenkre@Sun.COM char **gecos_v, **shell_v; 186*8040SBaban.Kenkre@Sun.COM char **homedir_v = NULL, *homedir = NULL; 187*8040SBaban.Kenkre@Sun.COM char *NULL_STR = ""; 188*8040SBaban.Kenkre@Sun.COM 189*8040SBaban.Kenkre@Sun.COM if (result == NULL) 190*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_PARSE); 191*8040SBaban.Kenkre@Sun.COM entry = adutils_getfirstentry(result); 192*8040SBaban.Kenkre@Sun.COM nss_result = NSS_STR_PARSE_PARSE; 193*8040SBaban.Kenkre@Sun.COM 194*8040SBaban.Kenkre@Sun.COM /* Create handles for idmap service */ 195*8040SBaban.Kenkre@Sun.COM if (be->ih == NULL && idmap_init(&be->ih) != 0) 196*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 197*8040SBaban.Kenkre@Sun.COM if (idmap_get_create(be->ih, &ig) != 0) 198*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 199*8040SBaban.Kenkre@Sun.COM 200*8040SBaban.Kenkre@Sun.COM /* Get name */ 201*8040SBaban.Kenkre@Sun.COM name_v = adutils_getattr(entry, _PWD_SAN); 202*8040SBaban.Kenkre@Sun.COM if (name_v == NULL || name_v[0] == NULL || *name_v[0] == '\0') 203*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 204*8040SBaban.Kenkre@Sun.COM 205*8040SBaban.Kenkre@Sun.COM /* Get domain */ 206*8040SBaban.Kenkre@Sun.COM dn_v = adutils_getattr(entry, _PWD_DN); 207*8040SBaban.Kenkre@Sun.COM if (dn_v == NULL || dn_v[0] == NULL || *dn_v[0] == '\0') 208*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 209*8040SBaban.Kenkre@Sun.COM domain = adutils_dn2dns(dn_v[0]); 210*8040SBaban.Kenkre@Sun.COM 211*8040SBaban.Kenkre@Sun.COM /* Get objectSID (in text format) */ 212*8040SBaban.Kenkre@Sun.COM sid_v = adutils_getattr(entry, _PWD_OBJSID); 213*8040SBaban.Kenkre@Sun.COM if (sid_v == NULL || sid_v[0] == NULL || *sid_v[0] == '\0') 214*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 215*8040SBaban.Kenkre@Sun.COM 216*8040SBaban.Kenkre@Sun.COM /* Break SID into prefix and rid */ 217*8040SBaban.Kenkre@Sun.COM if ((ptr = strrchr(sid_v[0], '-')) == NULL) 218*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 219*8040SBaban.Kenkre@Sun.COM *ptr = '\0'; 220*8040SBaban.Kenkre@Sun.COM end = ++ptr; 221*8040SBaban.Kenkre@Sun.COM tmp = strtoul(ptr, &end, 10); 222*8040SBaban.Kenkre@Sun.COM if (end == ptr || tmp > UINT32_MAX) 223*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 224*8040SBaban.Kenkre@Sun.COM urid = (uint32_t)tmp; 225*8040SBaban.Kenkre@Sun.COM 226*8040SBaban.Kenkre@Sun.COM /* We already have uid -- no need to call idmapd */ 227*8040SBaban.Kenkre@Sun.COM if (be->db_type == NSS_AD_DB_PASSWD_BYUID) 228*8040SBaban.Kenkre@Sun.COM uid = argp->key.uid; 229*8040SBaban.Kenkre@Sun.COM else 230*8040SBaban.Kenkre@Sun.COM uid = be->uid; 231*8040SBaban.Kenkre@Sun.COM 232*8040SBaban.Kenkre@Sun.COM /* Get primaryGroupID */ 233*8040SBaban.Kenkre@Sun.COM pgid_v = adutils_getattr(entry, _PWD_PRIMARYGROUPID); 234*8040SBaban.Kenkre@Sun.COM if (pgid_v == NULL || pgid_v[0] == NULL || *pgid_v[0] == '\0') 235*8040SBaban.Kenkre@Sun.COM /* 236*8040SBaban.Kenkre@Sun.COM * If primaryGroupID is not found then we request 237*8040SBaban.Kenkre@Sun.COM * a GID to be mapped to the given user's objectSID 238*8040SBaban.Kenkre@Sun.COM * (diagonal mapping) and use this GID as the primary 239*8040SBaban.Kenkre@Sun.COM * GID for the entry. 240*8040SBaban.Kenkre@Sun.COM */ 241*8040SBaban.Kenkre@Sun.COM grid = urid; 242*8040SBaban.Kenkre@Sun.COM else { 243*8040SBaban.Kenkre@Sun.COM end = pgid_v[0]; 244*8040SBaban.Kenkre@Sun.COM tmp = strtoul(pgid_v[0], &end, 10); 245*8040SBaban.Kenkre@Sun.COM if (end == pgid_v[0] || tmp > UINT32_MAX) 246*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 247*8040SBaban.Kenkre@Sun.COM grid = (uint32_t)tmp; 248*8040SBaban.Kenkre@Sun.COM } 249*8040SBaban.Kenkre@Sun.COM 250*8040SBaban.Kenkre@Sun.COM /* Map group SID to GID using idmap service */ 251*8040SBaban.Kenkre@Sun.COM if (idmap_get_gidbysid(ig, sid_v[0], grid, 0, &gid, &gstat) != 0) 252*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 253*8040SBaban.Kenkre@Sun.COM if (idmap_get_mappings(ig) != 0 || gstat != 0) { 254*8040SBaban.Kenkre@Sun.COM RESET_ERRNO(); 255*8040SBaban.Kenkre@Sun.COM goto result_pwd2str; 256*8040SBaban.Kenkre@Sun.COM } 257*8040SBaban.Kenkre@Sun.COM 258*8040SBaban.Kenkre@Sun.COM /* Get gecos, homedirectory and shell information if available */ 259*8040SBaban.Kenkre@Sun.COM gecos_v = adutils_getattr(entry, _PWD_CN); 260*8040SBaban.Kenkre@Sun.COM if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0') 261*8040SBaban.Kenkre@Sun.COM gecos_v = &NULL_STR; 262*8040SBaban.Kenkre@Sun.COM 263*8040SBaban.Kenkre@Sun.COM homedir_v = adutils_getattr(entry, _PWD_HOMEDIRECTORY); 264*8040SBaban.Kenkre@Sun.COM if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0') 265*8040SBaban.Kenkre@Sun.COM homedir = NULL_STR; 266*8040SBaban.Kenkre@Sun.COM else if ((homedir = process_homedir(homedir_v[0])) == NULL) 267*8040SBaban.Kenkre@Sun.COM homedir = NULL_STR; 268*8040SBaban.Kenkre@Sun.COM 269*8040SBaban.Kenkre@Sun.COM shell_v = adutils_getattr(entry, _PWD_LOGINSHELL); 270*8040SBaban.Kenkre@Sun.COM if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0') 271*8040SBaban.Kenkre@Sun.COM shell_v = &NULL_STR; 272*8040SBaban.Kenkre@Sun.COM 273*8040SBaban.Kenkre@Sun.COM if (update_buffer(be, argp, name_v[0], domain, uid, gid, 274*8040SBaban.Kenkre@Sun.COM gecos_v[0], homedir, shell_v[0]) < 0) 275*8040SBaban.Kenkre@Sun.COM nss_result = NSS_STR_PARSE_ERANGE; 276*8040SBaban.Kenkre@Sun.COM else 277*8040SBaban.Kenkre@Sun.COM nss_result = NSS_STR_PARSE_SUCCESS; 278*8040SBaban.Kenkre@Sun.COM 279*8040SBaban.Kenkre@Sun.COM result_pwd2str: 280*8040SBaban.Kenkre@Sun.COM idmap_get_destroy(ig); 281*8040SBaban.Kenkre@Sun.COM (void) idmap_fini(be->ih); 282*8040SBaban.Kenkre@Sun.COM be->ih = NULL; 283*8040SBaban.Kenkre@Sun.COM (void) adutils_freeresult(&be->result); 284*8040SBaban.Kenkre@Sun.COM free(domain); 285*8040SBaban.Kenkre@Sun.COM if (homedir != NULL_STR && homedir_v != NULL && 286*8040SBaban.Kenkre@Sun.COM homedir != homedir_v[0]) 287*8040SBaban.Kenkre@Sun.COM free(homedir); 288*8040SBaban.Kenkre@Sun.COM return ((int)nss_result); 289*8040SBaban.Kenkre@Sun.COM } 290*8040SBaban.Kenkre@Sun.COM 291*8040SBaban.Kenkre@Sun.COM /* 292*8040SBaban.Kenkre@Sun.COM * getbyname gets a passwd entry by winname. This function constructs an ldap 293*8040SBaban.Kenkre@Sun.COM * search filter using the name invocation parameter and the getpwnam search 294*8040SBaban.Kenkre@Sun.COM * filter defined. Once the filter is constructed, we search for a matching 295*8040SBaban.Kenkre@Sun.COM * entry and marshal the data results into struct passwd for the frontend 296*8040SBaban.Kenkre@Sun.COM * process. The function _nss_ad_passwd2ent performs the data marshaling. 297*8040SBaban.Kenkre@Sun.COM */ 298*8040SBaban.Kenkre@Sun.COM 299*8040SBaban.Kenkre@Sun.COM static nss_status_t 300*8040SBaban.Kenkre@Sun.COM getbyname(ad_backend_ptr be, void *a) 301*8040SBaban.Kenkre@Sun.COM { 302*8040SBaban.Kenkre@Sun.COM nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 303*8040SBaban.Kenkre@Sun.COM char *searchfilter; 304*8040SBaban.Kenkre@Sun.COM char name[SEARCHFILTERLEN]; 305*8040SBaban.Kenkre@Sun.COM char *dname; 306*8040SBaban.Kenkre@Sun.COM int filterlen, namelen; 307*8040SBaban.Kenkre@Sun.COM int flag; 308*8040SBaban.Kenkre@Sun.COM nss_status_t stat; 309*8040SBaban.Kenkre@Sun.COM idmap_stat idmaprc; 310*8040SBaban.Kenkre@Sun.COM uid_t uid; 311*8040SBaban.Kenkre@Sun.COM gid_t gid; 312*8040SBaban.Kenkre@Sun.COM int is_user, is_wuser, try_idmap; 313*8040SBaban.Kenkre@Sun.COM idmap_handle_t *ih; 314*8040SBaban.Kenkre@Sun.COM 315*8040SBaban.Kenkre@Sun.COM be->db_type = NSS_AD_DB_PASSWD_BYNAME; 316*8040SBaban.Kenkre@Sun.COM 317*8040SBaban.Kenkre@Sun.COM /* Sanitize name so that it can be used in our LDAP filter */ 318*8040SBaban.Kenkre@Sun.COM if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 319*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 320*8040SBaban.Kenkre@Sun.COM 321*8040SBaban.Kenkre@Sun.COM if ((dname = strchr(name, '@')) == NULL) 322*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 323*8040SBaban.Kenkre@Sun.COM 324*8040SBaban.Kenkre@Sun.COM *dname = '\0'; 325*8040SBaban.Kenkre@Sun.COM dname++; 326*8040SBaban.Kenkre@Sun.COM 327*8040SBaban.Kenkre@Sun.COM /* 328*8040SBaban.Kenkre@Sun.COM * Map the given name to UID using idmap service. If idmap 329*8040SBaban.Kenkre@Sun.COM * call fails then this will save us doing AD discovery and 330*8040SBaban.Kenkre@Sun.COM * AD lookup here. 331*8040SBaban.Kenkre@Sun.COM */ 332*8040SBaban.Kenkre@Sun.COM if (idmap_init(&be->ih) != IDMAP_SUCCESS) 333*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 334*8040SBaban.Kenkre@Sun.COM flag = (strcasecmp(dname, WK_DOMAIN) == 0) ? 335*8040SBaban.Kenkre@Sun.COM IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0; 336*8040SBaban.Kenkre@Sun.COM is_wuser = -1; 337*8040SBaban.Kenkre@Sun.COM is_user = 1; 338*8040SBaban.Kenkre@Sun.COM if (idmap_get_w2u_mapping(be->ih, NULL, NULL, name, 339*8040SBaban.Kenkre@Sun.COM dname, flag, &is_user, &is_wuser, &be->uid, NULL, 340*8040SBaban.Kenkre@Sun.COM NULL, NULL) != IDMAP_SUCCESS) { 341*8040SBaban.Kenkre@Sun.COM (void) idmap_fini(be->ih); 342*8040SBaban.Kenkre@Sun.COM be->ih = NULL; 343*8040SBaban.Kenkre@Sun.COM RESET_ERRNO(); 344*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 345*8040SBaban.Kenkre@Sun.COM } 346*8040SBaban.Kenkre@Sun.COM 347*8040SBaban.Kenkre@Sun.COM /* If this is not a Well-Known SID then try AD lookup. */ 348*8040SBaban.Kenkre@Sun.COM if (strcasecmp(dname, WK_DOMAIN) != 0) { 349*8040SBaban.Kenkre@Sun.COM /* Assemble filter using the given name */ 350*8040SBaban.Kenkre@Sun.COM namelen = strlen(name); 351*8040SBaban.Kenkre@Sun.COM filterlen = snprintf(NULL, 0, _F_GETPWNAM, namelen, name) + 1; 352*8040SBaban.Kenkre@Sun.COM if ((searchfilter = (char *)malloc(filterlen)) == NULL) 353*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 354*8040SBaban.Kenkre@Sun.COM (void) snprintf(searchfilter, filterlen, _F_GETPWNAM, 355*8040SBaban.Kenkre@Sun.COM namelen, name); 356*8040SBaban.Kenkre@Sun.COM stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter, 357*8040SBaban.Kenkre@Sun.COM dname, &try_idmap); 358*8040SBaban.Kenkre@Sun.COM free(searchfilter); 359*8040SBaban.Kenkre@Sun.COM 360*8040SBaban.Kenkre@Sun.COM if (!try_idmap) { 361*8040SBaban.Kenkre@Sun.COM (void) idmap_fini(be->ih); 362*8040SBaban.Kenkre@Sun.COM be->ih = NULL; 363*8040SBaban.Kenkre@Sun.COM return (stat); 364*8040SBaban.Kenkre@Sun.COM } 365*8040SBaban.Kenkre@Sun.COM 366*8040SBaban.Kenkre@Sun.COM } 367*8040SBaban.Kenkre@Sun.COM 368*8040SBaban.Kenkre@Sun.COM /* 369*8040SBaban.Kenkre@Sun.COM * Either this is a Well-Known SID or AD lookup failed. Map 370*8040SBaban.Kenkre@Sun.COM * the given name to GID using idmap service and construct 371*8040SBaban.Kenkre@Sun.COM * the passwd entry. 372*8040SBaban.Kenkre@Sun.COM */ 373*8040SBaban.Kenkre@Sun.COM is_wuser = -1; 374*8040SBaban.Kenkre@Sun.COM is_user = 0; /* Map name to primary gid */ 375*8040SBaban.Kenkre@Sun.COM idmaprc = idmap_get_w2u_mapping(be->ih, NULL, NULL, name, dname, 376*8040SBaban.Kenkre@Sun.COM flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL); 377*8040SBaban.Kenkre@Sun.COM (void) idmap_fini(be->ih); 378*8040SBaban.Kenkre@Sun.COM be->ih = NULL; 379*8040SBaban.Kenkre@Sun.COM if (idmaprc != IDMAP_SUCCESS) { 380*8040SBaban.Kenkre@Sun.COM RESET_ERRNO(); 381*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 382*8040SBaban.Kenkre@Sun.COM } 383*8040SBaban.Kenkre@Sun.COM 384*8040SBaban.Kenkre@Sun.COM /* Create passwd(4) style string */ 385*8040SBaban.Kenkre@Sun.COM if (update_buffer(be, argp, name, dname, 386*8040SBaban.Kenkre@Sun.COM be->uid, gid, "", "", "") < 0) 387*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 388*8040SBaban.Kenkre@Sun.COM 389*8040SBaban.Kenkre@Sun.COM /* Marshall the data, sanitize the return status and return */ 390*8040SBaban.Kenkre@Sun.COM stat = _nss_ad_marshall_data(be, argp); 391*8040SBaban.Kenkre@Sun.COM return (_nss_ad_sanitize_status(be, argp, stat)); 392*8040SBaban.Kenkre@Sun.COM } 393*8040SBaban.Kenkre@Sun.COM 394*8040SBaban.Kenkre@Sun.COM 395*8040SBaban.Kenkre@Sun.COM /* 396*8040SBaban.Kenkre@Sun.COM * getbyuid gets a passwd entry by uid number. This function constructs an ldap 397*8040SBaban.Kenkre@Sun.COM * search filter using the uid invocation parameter and the getpwuid search 398*8040SBaban.Kenkre@Sun.COM * filter defined. Once the filter is constructed, we search for a matching 399*8040SBaban.Kenkre@Sun.COM * entry and marshal the data results into struct passwd for the frontend 400*8040SBaban.Kenkre@Sun.COM * process. The function _nss_ad_passwd2ent performs the data marshaling. 401*8040SBaban.Kenkre@Sun.COM */ 402*8040SBaban.Kenkre@Sun.COM 403*8040SBaban.Kenkre@Sun.COM static nss_status_t 404*8040SBaban.Kenkre@Sun.COM getbyuid(ad_backend_ptr be, void *a) 405*8040SBaban.Kenkre@Sun.COM { 406*8040SBaban.Kenkre@Sun.COM nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 407*8040SBaban.Kenkre@Sun.COM char searchfilter[ADUTILS_MAXHEXBINSID + 14]; 408*8040SBaban.Kenkre@Sun.COM char *sidprefix = NULL; 409*8040SBaban.Kenkre@Sun.COM idmap_rid_t rid; 410*8040SBaban.Kenkre@Sun.COM char cbinsid[ADUTILS_MAXHEXBINSID + 1]; 411*8040SBaban.Kenkre@Sun.COM char *winname = NULL, *windomain = NULL; 412*8040SBaban.Kenkre@Sun.COM int is_user, is_wuser; 413*8040SBaban.Kenkre@Sun.COM gid_t gid; 414*8040SBaban.Kenkre@Sun.COM idmap_stat idmaprc; 415*8040SBaban.Kenkre@Sun.COM int ret, try_idmap; 416*8040SBaban.Kenkre@Sun.COM nss_status_t stat; 417*8040SBaban.Kenkre@Sun.COM 418*8040SBaban.Kenkre@Sun.COM be->db_type = NSS_AD_DB_PASSWD_BYUID; 419*8040SBaban.Kenkre@Sun.COM 420*8040SBaban.Kenkre@Sun.COM stat = (nss_status_t)NSS_NOTFOUND; 421*8040SBaban.Kenkre@Sun.COM 422*8040SBaban.Kenkre@Sun.COM /* nss_ad does not support non ephemeral uids */ 423*8040SBaban.Kenkre@Sun.COM if (argp->key.uid <= MAXUID) 424*8040SBaban.Kenkre@Sun.COM goto out; 425*8040SBaban.Kenkre@Sun.COM 426*8040SBaban.Kenkre@Sun.COM /* Map the given UID to a SID using the idmap service */ 427*8040SBaban.Kenkre@Sun.COM if (idmap_init(&be->ih) != 0) 428*8040SBaban.Kenkre@Sun.COM goto out; 429*8040SBaban.Kenkre@Sun.COM if (idmap_get_u2w_mapping(be->ih, &argp->key.uid, NULL, 0, 430*8040SBaban.Kenkre@Sun.COM 1, NULL, &sidprefix, &rid, &winname, &windomain, 431*8040SBaban.Kenkre@Sun.COM NULL, NULL) != 0) { 432*8040SBaban.Kenkre@Sun.COM RESET_ERRNO(); 433*8040SBaban.Kenkre@Sun.COM goto out; 434*8040SBaban.Kenkre@Sun.COM } 435*8040SBaban.Kenkre@Sun.COM 436*8040SBaban.Kenkre@Sun.COM /* 437*8040SBaban.Kenkre@Sun.COM * NULL winname implies a local SID or unresolvable SID both of 438*8040SBaban.Kenkre@Sun.COM * which cannot be used to generated passwd(4) entry 439*8040SBaban.Kenkre@Sun.COM */ 440*8040SBaban.Kenkre@Sun.COM if (winname == NULL) 441*8040SBaban.Kenkre@Sun.COM goto out; 442*8040SBaban.Kenkre@Sun.COM 443*8040SBaban.Kenkre@Sun.COM /* If this is not a Well-Known SID try AD lookup */ 444*8040SBaban.Kenkre@Sun.COM if (windomain != NULL && strcasecmp(windomain, WK_DOMAIN) != 0) { 445*8040SBaban.Kenkre@Sun.COM if (adutils_txtsid2hexbinsid(sidprefix, &rid, 446*8040SBaban.Kenkre@Sun.COM &cbinsid[0], sizeof (cbinsid)) != 0) 447*8040SBaban.Kenkre@Sun.COM goto out; 448*8040SBaban.Kenkre@Sun.COM 449*8040SBaban.Kenkre@Sun.COM ret = snprintf(searchfilter, sizeof (searchfilter), 450*8040SBaban.Kenkre@Sun.COM _F_GETPWUID, cbinsid); 451*8040SBaban.Kenkre@Sun.COM if (ret >= sizeof (searchfilter) || ret < 0) 452*8040SBaban.Kenkre@Sun.COM goto out; 453*8040SBaban.Kenkre@Sun.COM 454*8040SBaban.Kenkre@Sun.COM stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter, 455*8040SBaban.Kenkre@Sun.COM windomain, &try_idmap); 456*8040SBaban.Kenkre@Sun.COM 457*8040SBaban.Kenkre@Sun.COM if (!try_idmap) 458*8040SBaban.Kenkre@Sun.COM goto out; 459*8040SBaban.Kenkre@Sun.COM } 460*8040SBaban.Kenkre@Sun.COM 461*8040SBaban.Kenkre@Sun.COM /* Map winname to primary gid using idmap service */ 462*8040SBaban.Kenkre@Sun.COM is_user = 0; 463*8040SBaban.Kenkre@Sun.COM is_wuser = -1; 464*8040SBaban.Kenkre@Sun.COM idmaprc = idmap_get_w2u_mapping(be->ih, NULL, NULL, 465*8040SBaban.Kenkre@Sun.COM winname, windomain, 0, &is_user, &is_wuser, &gid, 466*8040SBaban.Kenkre@Sun.COM NULL, NULL, NULL); 467*8040SBaban.Kenkre@Sun.COM 468*8040SBaban.Kenkre@Sun.COM (void) idmap_fini(be->ih); 469*8040SBaban.Kenkre@Sun.COM be->ih = NULL; 470*8040SBaban.Kenkre@Sun.COM 471*8040SBaban.Kenkre@Sun.COM if (idmaprc != IDMAP_SUCCESS) { 472*8040SBaban.Kenkre@Sun.COM RESET_ERRNO(); 473*8040SBaban.Kenkre@Sun.COM goto out; 474*8040SBaban.Kenkre@Sun.COM } 475*8040SBaban.Kenkre@Sun.COM 476*8040SBaban.Kenkre@Sun.COM /* Create passwd(4) style string */ 477*8040SBaban.Kenkre@Sun.COM if (update_buffer(be, argp, winname, windomain, 478*8040SBaban.Kenkre@Sun.COM argp->key.uid, gid, "", "", "") < 0) 479*8040SBaban.Kenkre@Sun.COM goto out; 480*8040SBaban.Kenkre@Sun.COM 481*8040SBaban.Kenkre@Sun.COM /* Marshall the data, sanitize the return status and return */ 482*8040SBaban.Kenkre@Sun.COM stat = _nss_ad_marshall_data(be, argp); 483*8040SBaban.Kenkre@Sun.COM stat = _nss_ad_sanitize_status(be, argp, stat); 484*8040SBaban.Kenkre@Sun.COM 485*8040SBaban.Kenkre@Sun.COM out: 486*8040SBaban.Kenkre@Sun.COM idmap_free(sidprefix); 487*8040SBaban.Kenkre@Sun.COM idmap_free(winname); 488*8040SBaban.Kenkre@Sun.COM idmap_free(windomain); 489*8040SBaban.Kenkre@Sun.COM (void) idmap_fini(be->ih); 490*8040SBaban.Kenkre@Sun.COM be->ih = NULL; 491*8040SBaban.Kenkre@Sun.COM return (stat); 492*8040SBaban.Kenkre@Sun.COM } 493*8040SBaban.Kenkre@Sun.COM 494*8040SBaban.Kenkre@Sun.COM static ad_backend_op_t passwd_ops[] = { 495*8040SBaban.Kenkre@Sun.COM _nss_ad_destr, 496*8040SBaban.Kenkre@Sun.COM _nss_ad_endent, 497*8040SBaban.Kenkre@Sun.COM _nss_ad_setent, 498*8040SBaban.Kenkre@Sun.COM _nss_ad_getent, 499*8040SBaban.Kenkre@Sun.COM getbyname, 500*8040SBaban.Kenkre@Sun.COM getbyuid 501*8040SBaban.Kenkre@Sun.COM }; 502*8040SBaban.Kenkre@Sun.COM 503*8040SBaban.Kenkre@Sun.COM /* 504*8040SBaban.Kenkre@Sun.COM * _nss_ad_passwd_constr is where life begins. This function calls the 505*8040SBaban.Kenkre@Sun.COM * generic AD constructor function to define and build the abstract 506*8040SBaban.Kenkre@Sun.COM * data types required to support AD operations. 507*8040SBaban.Kenkre@Sun.COM */ 508*8040SBaban.Kenkre@Sun.COM 509*8040SBaban.Kenkre@Sun.COM /*ARGSUSED0*/ 510*8040SBaban.Kenkre@Sun.COM nss_backend_t * 511*8040SBaban.Kenkre@Sun.COM _nss_ad_passwd_constr(const char *dummy1, const char *dummy2, 512*8040SBaban.Kenkre@Sun.COM const char *dummy3) 513*8040SBaban.Kenkre@Sun.COM { 514*8040SBaban.Kenkre@Sun.COM 515*8040SBaban.Kenkre@Sun.COM return ((nss_backend_t *)_nss_ad_constr(passwd_ops, 516*8040SBaban.Kenkre@Sun.COM sizeof (passwd_ops)/sizeof (passwd_ops[0]), 517*8040SBaban.Kenkre@Sun.COM _PASSWD, pwd_attrs, _nss_ad_passwd2str)); 518*8040SBaban.Kenkre@Sun.COM } 519