12b4a7802SBaban Kenkre /*
22b4a7802SBaban Kenkre * CDDL HEADER START
32b4a7802SBaban Kenkre *
42b4a7802SBaban Kenkre * The contents of this file are subject to the terms of the
52b4a7802SBaban Kenkre * Common Development and Distribution License (the "License").
62b4a7802SBaban Kenkre * You may not use this file except in compliance with the License.
72b4a7802SBaban Kenkre *
82b4a7802SBaban Kenkre * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92b4a7802SBaban Kenkre * or http://www.opensolaris.org/os/licensing.
102b4a7802SBaban Kenkre * See the License for the specific language governing permissions
112b4a7802SBaban Kenkre * and limitations under the License.
122b4a7802SBaban Kenkre *
132b4a7802SBaban Kenkre * When distributing Covered Code, include this CDDL HEADER in each
142b4a7802SBaban Kenkre * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152b4a7802SBaban Kenkre * If applicable, add the following below this CDDL HEADER, with the
162b4a7802SBaban Kenkre * fields enclosed by brackets "[]" replaced with your own identifying
172b4a7802SBaban Kenkre * information: Portions Copyright [yyyy] [name of copyright owner]
182b4a7802SBaban Kenkre *
192b4a7802SBaban Kenkre * CDDL HEADER END
202b4a7802SBaban Kenkre */
212b4a7802SBaban Kenkre /*
221fdeec65Sjoyce mcintosh * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
232b4a7802SBaban Kenkre */
242b4a7802SBaban Kenkre
252b4a7802SBaban Kenkre #include <pwd.h>
262b4a7802SBaban Kenkre #include <idmap.h>
272b4a7802SBaban Kenkre #include <ctype.h>
282b4a7802SBaban Kenkre #include "ad_common.h"
292b4a7802SBaban Kenkre
302b4a7802SBaban Kenkre /* passwd attributes and filters */
312b4a7802SBaban Kenkre #define _PWD_DN "dn"
322b4a7802SBaban Kenkre #define _PWD_SAN "sAMAccountName"
332b4a7802SBaban Kenkre #define _PWD_OBJSID "objectSid"
342b4a7802SBaban Kenkre #define _PWD_PRIMARYGROUPID "primaryGroupID"
352b4a7802SBaban Kenkre #define _PWD_CN "cn"
362b4a7802SBaban Kenkre #define _PWD_HOMEDIRECTORY "homedirectory"
372b4a7802SBaban Kenkre #define _PWD_LOGINSHELL "loginshell"
382b4a7802SBaban Kenkre #define _PWD_OBJCLASS "objectClass"
392b4a7802SBaban Kenkre
402b4a7802SBaban Kenkre #define _F_GETPWNAM "(sAMAccountName=%.*s)"
412b4a7802SBaban Kenkre #define _F_GETPWUID "(objectSid=%s)"
422b4a7802SBaban Kenkre
432b4a7802SBaban Kenkre static const char *pwd_attrs[] = {
442b4a7802SBaban Kenkre _PWD_SAN,
452b4a7802SBaban Kenkre _PWD_OBJSID,
462b4a7802SBaban Kenkre _PWD_PRIMARYGROUPID,
472b4a7802SBaban Kenkre _PWD_CN,
482b4a7802SBaban Kenkre _PWD_HOMEDIRECTORY,
492b4a7802SBaban Kenkre _PWD_LOGINSHELL,
502b4a7802SBaban Kenkre _PWD_OBJCLASS,
512b4a7802SBaban Kenkre (char *)NULL
522b4a7802SBaban Kenkre };
532b4a7802SBaban Kenkre
542b4a7802SBaban Kenkre static int
update_buffer(ad_backend_ptr be,nss_XbyY_args_t * argp,const char * name,const char * domain,uid_t uid,gid_t gid,const char * gecos,const char * homedir,const char * shell)552b4a7802SBaban Kenkre update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp,
562b4a7802SBaban Kenkre const char *name, const char *domain,
572b4a7802SBaban Kenkre uid_t uid, gid_t gid, const char *gecos,
582b4a7802SBaban Kenkre const char *homedir, const char *shell)
592b4a7802SBaban Kenkre {
602b4a7802SBaban Kenkre int buflen;
612b4a7802SBaban Kenkre char *buffer;
622b4a7802SBaban Kenkre
632b4a7802SBaban Kenkre if (be->db_type == NSS_AD_DB_PASSWD_BYNAME) {
642b4a7802SBaban Kenkre /*
652b4a7802SBaban Kenkre * The canonical name obtained from AD lookup may not match
662b4a7802SBaban Kenkre * the case of the name (i.e. key) in the request. Therefore,
672b4a7802SBaban Kenkre * use the name from the request to construct the result.
682b4a7802SBaban Kenkre */
692b4a7802SBaban Kenkre buflen = snprintf(NULL, 0, "%s:%s:%u:%u:%s:%s:%s",
702b4a7802SBaban Kenkre argp->key.name, "x", uid, gid, gecos, homedir, shell) + 1;
712b4a7802SBaban Kenkre } else {
722b4a7802SBaban Kenkre if (domain == NULL)
732b4a7802SBaban Kenkre domain = WK_DOMAIN;
742b4a7802SBaban Kenkre buflen = snprintf(NULL, 0, "%s@%s:%s:%u:%u:%s:%s:%s",
752b4a7802SBaban Kenkre name, domain, "x", uid, gid, gecos, homedir, shell) + 1;
762b4a7802SBaban Kenkre }
772b4a7802SBaban Kenkre
782b4a7802SBaban Kenkre
792b4a7802SBaban Kenkre if (argp->buf.result != NULL) {
802b4a7802SBaban Kenkre buffer = be->buffer = malloc(buflen);
812b4a7802SBaban Kenkre if (be->buffer == NULL)
822b4a7802SBaban Kenkre return (-1);
832b4a7802SBaban Kenkre be->buflen = buflen;
842b4a7802SBaban Kenkre } else {
852b4a7802SBaban Kenkre if (buflen > argp->buf.buflen)
862b4a7802SBaban Kenkre return (-1);
872b4a7802SBaban Kenkre buflen = argp->buf.buflen;
882b4a7802SBaban Kenkre buffer = argp->buf.buffer;
892b4a7802SBaban Kenkre }
902b4a7802SBaban Kenkre
912b4a7802SBaban Kenkre if (be->db_type == NSS_AD_DB_PASSWD_BYNAME)
922b4a7802SBaban Kenkre (void) snprintf(buffer, buflen, "%s:%s:%u:%u:%s:%s:%s",
932b4a7802SBaban Kenkre argp->key.name, "x", uid, gid, gecos, homedir, shell);
942b4a7802SBaban Kenkre else
952b4a7802SBaban Kenkre (void) snprintf(buffer, buflen, "%s@%s:%s:%u:%u:%s:%s:%s",
962b4a7802SBaban Kenkre name, domain, "x", uid, gid, gecos, homedir, shell);
972b4a7802SBaban Kenkre return (0);
982b4a7802SBaban Kenkre }
992b4a7802SBaban Kenkre
1002b4a7802SBaban Kenkre
1012b4a7802SBaban Kenkre #define NET_SCHEME "/net"
1022b4a7802SBaban Kenkre
1032b4a7802SBaban Kenkre /*
1042b4a7802SBaban Kenkre * 1) If the homeDirectory string is in UNC format then convert it into
1052b4a7802SBaban Kenkre * a /net format. This needs to be revisited later but is fine for now
1062b4a7802SBaban Kenkre * because Solaris does not support -hosts automount map for CIFS yet.
1072b4a7802SBaban Kenkre *
1082b4a7802SBaban Kenkre * 2) If homeDirectory contains ':' then return NULL because ':' is the
1092b4a7802SBaban Kenkre * delimiter in passwd entries and may break apps that parse these entries.
1102b4a7802SBaban Kenkre *
1112b4a7802SBaban Kenkre * 3) For all other cases return the same string that was passed to
1122b4a7802SBaban Kenkre * this function.
1132b4a7802SBaban Kenkre */
1142b4a7802SBaban Kenkre static
1152b4a7802SBaban Kenkre char *
process_homedir(char * homedir)1162b4a7802SBaban Kenkre process_homedir(char *homedir)
1172b4a7802SBaban Kenkre {
1182b4a7802SBaban Kenkre size_t len, smb_len;
1192b4a7802SBaban Kenkre char *smb_homedir;
1202b4a7802SBaban Kenkre int i, slash = 0;
1212b4a7802SBaban Kenkre
1222b4a7802SBaban Kenkre len = strlen(homedir);
1232b4a7802SBaban Kenkre
1242b4a7802SBaban Kenkre if (strchr(homedir, ':') != NULL)
1252b4a7802SBaban Kenkre /*
1262b4a7802SBaban Kenkre * Ignore paths that have colon ':' because ':' is a
1272b4a7802SBaban Kenkre * delimiter for the passwd entry.
1282b4a7802SBaban Kenkre */
1292b4a7802SBaban Kenkre return (NULL);
1302b4a7802SBaban Kenkre
1312b4a7802SBaban Kenkre if (!(len > 1 && homedir[0] == '\\' && homedir[1] == '\\'))
1322b4a7802SBaban Kenkre /* Keep homedir intact if not in UNC format */
1332b4a7802SBaban Kenkre return (homedir);
1342b4a7802SBaban Kenkre
1352b4a7802SBaban Kenkre /*
1362b4a7802SBaban Kenkre * Convert UNC string into /net format
1372b4a7802SBaban Kenkre * Example: \\server\abc -> /net/server/abc
1382b4a7802SBaban Kenkre */
1392b4a7802SBaban Kenkre smb_len = len + 1 + sizeof (NET_SCHEME);
1402b4a7802SBaban Kenkre if ((smb_homedir = calloc(1, smb_len)) == NULL)
1412b4a7802SBaban Kenkre return (NULL);
1422b4a7802SBaban Kenkre (void) strlcpy(smb_homedir, NET_SCHEME, smb_len);
1432b4a7802SBaban Kenkre for (i = strlen(smb_homedir); *homedir != '\0'; homedir++) {
1442b4a7802SBaban Kenkre if (*homedir == '\\') {
1452b4a7802SBaban Kenkre /* Reduce double backslashes into one */
1462b4a7802SBaban Kenkre if (slash)
1472b4a7802SBaban Kenkre slash = 0;
1482b4a7802SBaban Kenkre else {
1492b4a7802SBaban Kenkre slash = 1;
1502b4a7802SBaban Kenkre smb_homedir[i++] = '/';
1512b4a7802SBaban Kenkre }
1522b4a7802SBaban Kenkre } else {
1532b4a7802SBaban Kenkre smb_homedir[i++] = *homedir;
1542b4a7802SBaban Kenkre slash = 0;
1552b4a7802SBaban Kenkre }
1562b4a7802SBaban Kenkre }
1572b4a7802SBaban Kenkre return (smb_homedir);
1582b4a7802SBaban Kenkre }
1592b4a7802SBaban Kenkre
1602b4a7802SBaban Kenkre /*
1612b4a7802SBaban Kenkre * _nss_ad_passwd2str is the data marshaling method for the passwd getXbyY
1622b4a7802SBaban Kenkre * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
1632b4a7802SBaban Kenkre * called after a successful AD search has been performed. This method will
1642b4a7802SBaban Kenkre * parse the AD search values into the file format.
1652b4a7802SBaban Kenkre * e.g.
1662b4a7802SBaban Kenkre *
1672b4a7802SBaban Kenkre * blue@whale:x:123456:10:Blue Whale:/:
1682b4a7802SBaban Kenkre *
1692b4a7802SBaban Kenkre */
1702b4a7802SBaban Kenkre static int
_nss_ad_passwd2str(ad_backend_ptr be,nss_XbyY_args_t * argp)1712b4a7802SBaban Kenkre _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp)
1722b4a7802SBaban Kenkre {
1732b4a7802SBaban Kenkre int nss_result;
1742b4a7802SBaban Kenkre adutils_result_t *result = be->result;
1752b4a7802SBaban Kenkre const adutils_entry_t *entry;
1762b4a7802SBaban Kenkre char **sid_v, *ptr, **pgid_v, *end;
1772b4a7802SBaban Kenkre ulong_t tmp;
1782b4a7802SBaban Kenkre uint32_t urid, grid;
1792b4a7802SBaban Kenkre uid_t uid;
1802b4a7802SBaban Kenkre gid_t gid;
1812b4a7802SBaban Kenkre idmap_stat gstat;
1822b4a7802SBaban Kenkre idmap_get_handle_t *ig = NULL;
1832b4a7802SBaban Kenkre char **name_v, **dn_v, *domain = NULL;
1842b4a7802SBaban Kenkre char **gecos_v, **shell_v;
1852b4a7802SBaban Kenkre char **homedir_v = NULL, *homedir = NULL;
1862b4a7802SBaban Kenkre char *NULL_STR = "";
1872b4a7802SBaban Kenkre
1882b4a7802SBaban Kenkre if (result == NULL)
1892b4a7802SBaban Kenkre return (NSS_STR_PARSE_PARSE);
1902b4a7802SBaban Kenkre entry = adutils_getfirstentry(result);
1912b4a7802SBaban Kenkre nss_result = NSS_STR_PARSE_PARSE;
1922b4a7802SBaban Kenkre
1932b4a7802SBaban Kenkre /* Create handles for idmap service */
1941fdeec65Sjoyce mcintosh if (idmap_get_create(&ig) != 0)
1952b4a7802SBaban Kenkre goto result_pwd2str;
1962b4a7802SBaban Kenkre
1972b4a7802SBaban Kenkre /* Get name */
1982b4a7802SBaban Kenkre name_v = adutils_getattr(entry, _PWD_SAN);
1992b4a7802SBaban Kenkre if (name_v == NULL || name_v[0] == NULL || *name_v[0] == '\0')
2002b4a7802SBaban Kenkre goto result_pwd2str;
2012b4a7802SBaban Kenkre
2022b4a7802SBaban Kenkre /* Get domain */
2032b4a7802SBaban Kenkre dn_v = adutils_getattr(entry, _PWD_DN);
2042b4a7802SBaban Kenkre if (dn_v == NULL || dn_v[0] == NULL || *dn_v[0] == '\0')
2052b4a7802SBaban Kenkre goto result_pwd2str;
2062b4a7802SBaban Kenkre domain = adutils_dn2dns(dn_v[0]);
2072b4a7802SBaban Kenkre
2082b4a7802SBaban Kenkre /* Get objectSID (in text format) */
2092b4a7802SBaban Kenkre sid_v = adutils_getattr(entry, _PWD_OBJSID);
2102b4a7802SBaban Kenkre if (sid_v == NULL || sid_v[0] == NULL || *sid_v[0] == '\0')
2112b4a7802SBaban Kenkre goto result_pwd2str;
2122b4a7802SBaban Kenkre
2132b4a7802SBaban Kenkre /* Break SID into prefix and rid */
2142b4a7802SBaban Kenkre if ((ptr = strrchr(sid_v[0], '-')) == NULL)
2152b4a7802SBaban Kenkre goto result_pwd2str;
2162b4a7802SBaban Kenkre *ptr = '\0';
2172b4a7802SBaban Kenkre end = ++ptr;
2182b4a7802SBaban Kenkre tmp = strtoul(ptr, &end, 10);
2192b4a7802SBaban Kenkre if (end == ptr || tmp > UINT32_MAX)
2202b4a7802SBaban Kenkre goto result_pwd2str;
2212b4a7802SBaban Kenkre urid = (uint32_t)tmp;
2222b4a7802SBaban Kenkre
2232b4a7802SBaban Kenkre /* We already have uid -- no need to call idmapd */
2242b4a7802SBaban Kenkre if (be->db_type == NSS_AD_DB_PASSWD_BYUID)
2252b4a7802SBaban Kenkre uid = argp->key.uid;
2262b4a7802SBaban Kenkre else
2272b4a7802SBaban Kenkre uid = be->uid;
2282b4a7802SBaban Kenkre
2292b4a7802SBaban Kenkre /* Get primaryGroupID */
2302b4a7802SBaban Kenkre pgid_v = adutils_getattr(entry, _PWD_PRIMARYGROUPID);
2312b4a7802SBaban Kenkre if (pgid_v == NULL || pgid_v[0] == NULL || *pgid_v[0] == '\0')
2322b4a7802SBaban Kenkre /*
2332b4a7802SBaban Kenkre * If primaryGroupID is not found then we request
2342b4a7802SBaban Kenkre * a GID to be mapped to the given user's objectSID
2352b4a7802SBaban Kenkre * (diagonal mapping) and use this GID as the primary
2362b4a7802SBaban Kenkre * GID for the entry.
2372b4a7802SBaban Kenkre */
2382b4a7802SBaban Kenkre grid = urid;
2392b4a7802SBaban Kenkre else {
2402b4a7802SBaban Kenkre end = pgid_v[0];
2412b4a7802SBaban Kenkre tmp = strtoul(pgid_v[0], &end, 10);
2422b4a7802SBaban Kenkre if (end == pgid_v[0] || tmp > UINT32_MAX)
2432b4a7802SBaban Kenkre goto result_pwd2str;
2442b4a7802SBaban Kenkre grid = (uint32_t)tmp;
2452b4a7802SBaban Kenkre }
2462b4a7802SBaban Kenkre
2472b4a7802SBaban Kenkre /* Map group SID to GID using idmap service */
2482b4a7802SBaban Kenkre if (idmap_get_gidbysid(ig, sid_v[0], grid, 0, &gid, &gstat) != 0)
2492b4a7802SBaban Kenkre goto result_pwd2str;
2502b4a7802SBaban Kenkre if (idmap_get_mappings(ig) != 0 || gstat != 0) {
2512b4a7802SBaban Kenkre RESET_ERRNO();
2522b4a7802SBaban Kenkre goto result_pwd2str;
2532b4a7802SBaban Kenkre }
2542b4a7802SBaban Kenkre
2552b4a7802SBaban Kenkre /* Get gecos, homedirectory and shell information if available */
2562b4a7802SBaban Kenkre gecos_v = adutils_getattr(entry, _PWD_CN);
2572b4a7802SBaban Kenkre if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
2582b4a7802SBaban Kenkre gecos_v = &NULL_STR;
2592b4a7802SBaban Kenkre
2602b4a7802SBaban Kenkre homedir_v = adutils_getattr(entry, _PWD_HOMEDIRECTORY);
2612b4a7802SBaban Kenkre if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
2622b4a7802SBaban Kenkre homedir = NULL_STR;
2632b4a7802SBaban Kenkre else if ((homedir = process_homedir(homedir_v[0])) == NULL)
2642b4a7802SBaban Kenkre homedir = NULL_STR;
2652b4a7802SBaban Kenkre
2662b4a7802SBaban Kenkre shell_v = adutils_getattr(entry, _PWD_LOGINSHELL);
2672b4a7802SBaban Kenkre if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
2682b4a7802SBaban Kenkre shell_v = &NULL_STR;
2692b4a7802SBaban Kenkre
2702b4a7802SBaban Kenkre if (update_buffer(be, argp, name_v[0], domain, uid, gid,
2712b4a7802SBaban Kenkre gecos_v[0], homedir, shell_v[0]) < 0)
2722b4a7802SBaban Kenkre nss_result = NSS_STR_PARSE_ERANGE;
2732b4a7802SBaban Kenkre else
2742b4a7802SBaban Kenkre nss_result = NSS_STR_PARSE_SUCCESS;
2752b4a7802SBaban Kenkre
2762b4a7802SBaban Kenkre result_pwd2str:
2772b4a7802SBaban Kenkre idmap_get_destroy(ig);
2782b4a7802SBaban Kenkre (void) adutils_freeresult(&be->result);
2792b4a7802SBaban Kenkre free(domain);
2802b4a7802SBaban Kenkre if (homedir != NULL_STR && homedir_v != NULL &&
2812b4a7802SBaban Kenkre homedir != homedir_v[0])
2822b4a7802SBaban Kenkre free(homedir);
2832b4a7802SBaban Kenkre return ((int)nss_result);
2842b4a7802SBaban Kenkre }
2852b4a7802SBaban Kenkre
2862b4a7802SBaban Kenkre /*
2872b4a7802SBaban Kenkre * getbyname gets a passwd entry by winname. This function constructs an ldap
2882b4a7802SBaban Kenkre * search filter using the name invocation parameter and the getpwnam search
2892b4a7802SBaban Kenkre * filter defined. Once the filter is constructed, we search for a matching
2902b4a7802SBaban Kenkre * entry and marshal the data results into struct passwd for the frontend
2912b4a7802SBaban Kenkre * process. The function _nss_ad_passwd2ent performs the data marshaling.
2922b4a7802SBaban Kenkre */
2932b4a7802SBaban Kenkre
2942b4a7802SBaban Kenkre static nss_status_t
getbyname(ad_backend_ptr be,void * a)2952b4a7802SBaban Kenkre getbyname(ad_backend_ptr be, void *a)
2962b4a7802SBaban Kenkre {
2972b4a7802SBaban Kenkre nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2982b4a7802SBaban Kenkre char *searchfilter;
2992b4a7802SBaban Kenkre char name[SEARCHFILTERLEN];
3002b4a7802SBaban Kenkre char *dname;
3012b4a7802SBaban Kenkre int filterlen, namelen;
3022b4a7802SBaban Kenkre int flag;
3032b4a7802SBaban Kenkre nss_status_t stat;
3042b4a7802SBaban Kenkre idmap_stat idmaprc;
3052b4a7802SBaban Kenkre uid_t uid;
3062b4a7802SBaban Kenkre gid_t gid;
3072b4a7802SBaban Kenkre int is_user, is_wuser, try_idmap;
3082b4a7802SBaban Kenkre
3092b4a7802SBaban Kenkre be->db_type = NSS_AD_DB_PASSWD_BYNAME;
3102b4a7802SBaban Kenkre
3112b4a7802SBaban Kenkre /* Sanitize name so that it can be used in our LDAP filter */
3122b4a7802SBaban Kenkre if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
3132b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
3142b4a7802SBaban Kenkre
3152b4a7802SBaban Kenkre if ((dname = strchr(name, '@')) == NULL)
3162b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
3172b4a7802SBaban Kenkre
3182b4a7802SBaban Kenkre *dname = '\0';
3192b4a7802SBaban Kenkre dname++;
3202b4a7802SBaban Kenkre
3212b4a7802SBaban Kenkre /*
3222b4a7802SBaban Kenkre * Map the given name to UID using idmap service. If idmap
3232b4a7802SBaban Kenkre * call fails then this will save us doing AD discovery and
3242b4a7802SBaban Kenkre * AD lookup here.
3252b4a7802SBaban Kenkre */
3262b4a7802SBaban Kenkre flag = (strcasecmp(dname, WK_DOMAIN) == 0) ?
3272b4a7802SBaban Kenkre IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0;
3282b4a7802SBaban Kenkre is_wuser = -1;
3292b4a7802SBaban Kenkre is_user = 1;
3301fdeec65Sjoyce mcintosh if (idmap_get_w2u_mapping(NULL, NULL, name,
3312b4a7802SBaban Kenkre dname, flag, &is_user, &is_wuser, &be->uid, NULL,
3322b4a7802SBaban Kenkre NULL, NULL) != IDMAP_SUCCESS) {
3332b4a7802SBaban Kenkre RESET_ERRNO();
3342b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
3352b4a7802SBaban Kenkre }
3362b4a7802SBaban Kenkre
3372b4a7802SBaban Kenkre /* If this is not a Well-Known SID then try AD lookup. */
3382b4a7802SBaban Kenkre if (strcasecmp(dname, WK_DOMAIN) != 0) {
3392b4a7802SBaban Kenkre /* Assemble filter using the given name */
3402b4a7802SBaban Kenkre namelen = strlen(name);
3412b4a7802SBaban Kenkre filterlen = snprintf(NULL, 0, _F_GETPWNAM, namelen, name) + 1;
3422b4a7802SBaban Kenkre if ((searchfilter = (char *)malloc(filterlen)) == NULL)
3432b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
3442b4a7802SBaban Kenkre (void) snprintf(searchfilter, filterlen, _F_GETPWNAM,
3452b4a7802SBaban Kenkre namelen, name);
3462b4a7802SBaban Kenkre stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
3472b4a7802SBaban Kenkre dname, &try_idmap);
3482b4a7802SBaban Kenkre free(searchfilter);
3492b4a7802SBaban Kenkre
3501fdeec65Sjoyce mcintosh if (!try_idmap)
3512b4a7802SBaban Kenkre return (stat);
3522b4a7802SBaban Kenkre
3532b4a7802SBaban Kenkre }
3542b4a7802SBaban Kenkre
3552b4a7802SBaban Kenkre /*
3562b4a7802SBaban Kenkre * Either this is a Well-Known SID or AD lookup failed. Map
3572b4a7802SBaban Kenkre * the given name to GID using idmap service and construct
3582b4a7802SBaban Kenkre * the passwd entry.
3592b4a7802SBaban Kenkre */
3602b4a7802SBaban Kenkre is_wuser = -1;
3612b4a7802SBaban Kenkre is_user = 0; /* Map name to primary gid */
3621fdeec65Sjoyce mcintosh idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
3632b4a7802SBaban Kenkre flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL);
3642b4a7802SBaban Kenkre if (idmaprc != IDMAP_SUCCESS) {
3652b4a7802SBaban Kenkre RESET_ERRNO();
3662b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
3672b4a7802SBaban Kenkre }
3682b4a7802SBaban Kenkre
369*bbf21555SRichard Lowe /* Create passwd(5) style string */
3702b4a7802SBaban Kenkre if (update_buffer(be, argp, name, dname,
3712b4a7802SBaban Kenkre be->uid, gid, "", "", "") < 0)
3722b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
3732b4a7802SBaban Kenkre
3742b4a7802SBaban Kenkre /* Marshall the data, sanitize the return status and return */
3752b4a7802SBaban Kenkre stat = _nss_ad_marshall_data(be, argp);
3762b4a7802SBaban Kenkre return (_nss_ad_sanitize_status(be, argp, stat));
3772b4a7802SBaban Kenkre }
3782b4a7802SBaban Kenkre
3792b4a7802SBaban Kenkre
3802b4a7802SBaban Kenkre /*
3812b4a7802SBaban Kenkre * getbyuid gets a passwd entry by uid number. This function constructs an ldap
3822b4a7802SBaban Kenkre * search filter using the uid invocation parameter and the getpwuid search
3832b4a7802SBaban Kenkre * filter defined. Once the filter is constructed, we search for a matching
3842b4a7802SBaban Kenkre * entry and marshal the data results into struct passwd for the frontend
3852b4a7802SBaban Kenkre * process. The function _nss_ad_passwd2ent performs the data marshaling.
3862b4a7802SBaban Kenkre */
3872b4a7802SBaban Kenkre
3882b4a7802SBaban Kenkre static nss_status_t
getbyuid(ad_backend_ptr be,void * a)3892b4a7802SBaban Kenkre getbyuid(ad_backend_ptr be, void *a)
3902b4a7802SBaban Kenkre {
3912b4a7802SBaban Kenkre nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
3922b4a7802SBaban Kenkre char searchfilter[ADUTILS_MAXHEXBINSID + 14];
3932b4a7802SBaban Kenkre char *sidprefix = NULL;
3942b4a7802SBaban Kenkre idmap_rid_t rid;
3952b4a7802SBaban Kenkre char cbinsid[ADUTILS_MAXHEXBINSID + 1];
3962b4a7802SBaban Kenkre char *winname = NULL, *windomain = NULL;
3972b4a7802SBaban Kenkre int is_user, is_wuser;
3982b4a7802SBaban Kenkre gid_t gid;
3992b4a7802SBaban Kenkre idmap_stat idmaprc;
4002b4a7802SBaban Kenkre int ret, try_idmap;
4012b4a7802SBaban Kenkre nss_status_t stat;
4022b4a7802SBaban Kenkre
4032b4a7802SBaban Kenkre be->db_type = NSS_AD_DB_PASSWD_BYUID;
4042b4a7802SBaban Kenkre
4052b4a7802SBaban Kenkre stat = (nss_status_t)NSS_NOTFOUND;
4062b4a7802SBaban Kenkre
4072b4a7802SBaban Kenkre /* nss_ad does not support non ephemeral uids */
4082b4a7802SBaban Kenkre if (argp->key.uid <= MAXUID)
4092b4a7802SBaban Kenkre goto out;
4102b4a7802SBaban Kenkre
4112b4a7802SBaban Kenkre /* Map the given UID to a SID using the idmap service */
4121fdeec65Sjoyce mcintosh if (idmap_get_u2w_mapping(&argp->key.uid, NULL, 0,
4132b4a7802SBaban Kenkre 1, NULL, &sidprefix, &rid, &winname, &windomain,
4142b4a7802SBaban Kenkre NULL, NULL) != 0) {
4152b4a7802SBaban Kenkre RESET_ERRNO();
4162b4a7802SBaban Kenkre goto out;
4172b4a7802SBaban Kenkre }
4182b4a7802SBaban Kenkre
4192b4a7802SBaban Kenkre /*
4202b4a7802SBaban Kenkre * NULL winname implies a local SID or unresolvable SID both of
421*bbf21555SRichard Lowe * which cannot be used to generated passwd(5) entry
4222b4a7802SBaban Kenkre */
4232b4a7802SBaban Kenkre if (winname == NULL)
4242b4a7802SBaban Kenkre goto out;
4252b4a7802SBaban Kenkre
4262b4a7802SBaban Kenkre /* If this is not a Well-Known SID try AD lookup */
4272b4a7802SBaban Kenkre if (windomain != NULL && strcasecmp(windomain, WK_DOMAIN) != 0) {
4282b4a7802SBaban Kenkre if (adutils_txtsid2hexbinsid(sidprefix, &rid,
4292b4a7802SBaban Kenkre &cbinsid[0], sizeof (cbinsid)) != 0)
4302b4a7802SBaban Kenkre goto out;
4312b4a7802SBaban Kenkre
4322b4a7802SBaban Kenkre ret = snprintf(searchfilter, sizeof (searchfilter),
4332b4a7802SBaban Kenkre _F_GETPWUID, cbinsid);
4342b4a7802SBaban Kenkre if (ret >= sizeof (searchfilter) || ret < 0)
4352b4a7802SBaban Kenkre goto out;
4362b4a7802SBaban Kenkre
4372b4a7802SBaban Kenkre stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
4382b4a7802SBaban Kenkre windomain, &try_idmap);
4392b4a7802SBaban Kenkre
4402b4a7802SBaban Kenkre if (!try_idmap)
4412b4a7802SBaban Kenkre goto out;
4422b4a7802SBaban Kenkre }
4432b4a7802SBaban Kenkre
4442b4a7802SBaban Kenkre /* Map winname to primary gid using idmap service */
4452b4a7802SBaban Kenkre is_user = 0;
4462b4a7802SBaban Kenkre is_wuser = -1;
4471fdeec65Sjoyce mcintosh idmaprc = idmap_get_w2u_mapping(NULL, NULL,
4482b4a7802SBaban Kenkre winname, windomain, 0, &is_user, &is_wuser, &gid,
4492b4a7802SBaban Kenkre NULL, NULL, NULL);
4502b4a7802SBaban Kenkre
4512b4a7802SBaban Kenkre if (idmaprc != IDMAP_SUCCESS) {
4522b4a7802SBaban Kenkre RESET_ERRNO();
4532b4a7802SBaban Kenkre goto out;
4542b4a7802SBaban Kenkre }
4552b4a7802SBaban Kenkre
456*bbf21555SRichard Lowe /* Create passwd(5) style string */
4572b4a7802SBaban Kenkre if (update_buffer(be, argp, winname, windomain,
4582b4a7802SBaban Kenkre argp->key.uid, gid, "", "", "") < 0)
4592b4a7802SBaban Kenkre goto out;
4602b4a7802SBaban Kenkre
4612b4a7802SBaban Kenkre /* Marshall the data, sanitize the return status and return */
4622b4a7802SBaban Kenkre stat = _nss_ad_marshall_data(be, argp);
4632b4a7802SBaban Kenkre stat = _nss_ad_sanitize_status(be, argp, stat);
4642b4a7802SBaban Kenkre
4652b4a7802SBaban Kenkre out:
4662b4a7802SBaban Kenkre idmap_free(sidprefix);
4672b4a7802SBaban Kenkre idmap_free(winname);
4682b4a7802SBaban Kenkre idmap_free(windomain);
4692b4a7802SBaban Kenkre return (stat);
4702b4a7802SBaban Kenkre }
4712b4a7802SBaban Kenkre
4722b4a7802SBaban Kenkre static ad_backend_op_t passwd_ops[] = {
4732b4a7802SBaban Kenkre _nss_ad_destr,
4742b4a7802SBaban Kenkre _nss_ad_endent,
4752b4a7802SBaban Kenkre _nss_ad_setent,
4762b4a7802SBaban Kenkre _nss_ad_getent,
4772b4a7802SBaban Kenkre getbyname,
4782b4a7802SBaban Kenkre getbyuid
4792b4a7802SBaban Kenkre };
4802b4a7802SBaban Kenkre
4812b4a7802SBaban Kenkre /*
4822b4a7802SBaban Kenkre * _nss_ad_passwd_constr is where life begins. This function calls the
4832b4a7802SBaban Kenkre * generic AD constructor function to define and build the abstract
4842b4a7802SBaban Kenkre * data types required to support AD operations.
4852b4a7802SBaban Kenkre */
4862b4a7802SBaban Kenkre
4872b4a7802SBaban Kenkre /*ARGSUSED0*/
4882b4a7802SBaban Kenkre nss_backend_t *
_nss_ad_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)4892b4a7802SBaban Kenkre _nss_ad_passwd_constr(const char *dummy1, const char *dummy2,
4902b4a7802SBaban Kenkre const char *dummy3)
4912b4a7802SBaban Kenkre {
4922b4a7802SBaban Kenkre
4932b4a7802SBaban Kenkre return ((nss_backend_t *)_nss_ad_constr(passwd_ops,
4942b4a7802SBaban Kenkre sizeof (passwd_ops)/sizeof (passwd_ops[0]),
4952b4a7802SBaban Kenkre _PASSWD, pwd_attrs, _nss_ad_passwd2str));
4962b4a7802SBaban Kenkre }
497