18040SBaban.Kenkre@Sun.COM /*
28040SBaban.Kenkre@Sun.COM * CDDL HEADER START
38040SBaban.Kenkre@Sun.COM *
48040SBaban.Kenkre@Sun.COM * The contents of this file are subject to the terms of the
58040SBaban.Kenkre@Sun.COM * Common Development and Distribution License (the "License").
68040SBaban.Kenkre@Sun.COM * You may not use this file except in compliance with the License.
78040SBaban.Kenkre@Sun.COM *
88040SBaban.Kenkre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98040SBaban.Kenkre@Sun.COM * or http://www.opensolaris.org/os/licensing.
108040SBaban.Kenkre@Sun.COM * See the License for the specific language governing permissions
118040SBaban.Kenkre@Sun.COM * and limitations under the License.
128040SBaban.Kenkre@Sun.COM *
138040SBaban.Kenkre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
148040SBaban.Kenkre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158040SBaban.Kenkre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
168040SBaban.Kenkre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
178040SBaban.Kenkre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
188040SBaban.Kenkre@Sun.COM *
198040SBaban.Kenkre@Sun.COM * CDDL HEADER END
208040SBaban.Kenkre@Sun.COM */
218040SBaban.Kenkre@Sun.COM /*
22*12914SJoyce.McIntosh@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
238040SBaban.Kenkre@Sun.COM */
248040SBaban.Kenkre@Sun.COM
258040SBaban.Kenkre@Sun.COM #include <pwd.h>
268040SBaban.Kenkre@Sun.COM #include <idmap.h>
278040SBaban.Kenkre@Sun.COM #include <ctype.h>
288040SBaban.Kenkre@Sun.COM #include "ad_common.h"
298040SBaban.Kenkre@Sun.COM
308040SBaban.Kenkre@Sun.COM /* passwd attributes and filters */
318040SBaban.Kenkre@Sun.COM #define _PWD_DN "dn"
328040SBaban.Kenkre@Sun.COM #define _PWD_SAN "sAMAccountName"
338040SBaban.Kenkre@Sun.COM #define _PWD_OBJSID "objectSid"
348040SBaban.Kenkre@Sun.COM #define _PWD_PRIMARYGROUPID "primaryGroupID"
358040SBaban.Kenkre@Sun.COM #define _PWD_CN "cn"
368040SBaban.Kenkre@Sun.COM #define _PWD_HOMEDIRECTORY "homedirectory"
378040SBaban.Kenkre@Sun.COM #define _PWD_LOGINSHELL "loginshell"
388040SBaban.Kenkre@Sun.COM #define _PWD_OBJCLASS "objectClass"
398040SBaban.Kenkre@Sun.COM
408040SBaban.Kenkre@Sun.COM #define _F_GETPWNAM "(sAMAccountName=%.*s)"
418040SBaban.Kenkre@Sun.COM #define _F_GETPWUID "(objectSid=%s)"
428040SBaban.Kenkre@Sun.COM
438040SBaban.Kenkre@Sun.COM static const char *pwd_attrs[] = {
448040SBaban.Kenkre@Sun.COM _PWD_SAN,
458040SBaban.Kenkre@Sun.COM _PWD_OBJSID,
468040SBaban.Kenkre@Sun.COM _PWD_PRIMARYGROUPID,
478040SBaban.Kenkre@Sun.COM _PWD_CN,
488040SBaban.Kenkre@Sun.COM _PWD_HOMEDIRECTORY,
498040SBaban.Kenkre@Sun.COM _PWD_LOGINSHELL,
508040SBaban.Kenkre@Sun.COM _PWD_OBJCLASS,
518040SBaban.Kenkre@Sun.COM (char *)NULL
528040SBaban.Kenkre@Sun.COM };
538040SBaban.Kenkre@Sun.COM
548040SBaban.Kenkre@Sun.COM 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)558040SBaban.Kenkre@Sun.COM update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp,
568040SBaban.Kenkre@Sun.COM const char *name, const char *domain,
578040SBaban.Kenkre@Sun.COM uid_t uid, gid_t gid, const char *gecos,
588040SBaban.Kenkre@Sun.COM const char *homedir, const char *shell)
598040SBaban.Kenkre@Sun.COM {
608040SBaban.Kenkre@Sun.COM int buflen;
618040SBaban.Kenkre@Sun.COM char *buffer;
628040SBaban.Kenkre@Sun.COM
638040SBaban.Kenkre@Sun.COM if (be->db_type == NSS_AD_DB_PASSWD_BYNAME) {
648040SBaban.Kenkre@Sun.COM /*
658040SBaban.Kenkre@Sun.COM * The canonical name obtained from AD lookup may not match
668040SBaban.Kenkre@Sun.COM * the case of the name (i.e. key) in the request. Therefore,
678040SBaban.Kenkre@Sun.COM * use the name from the request to construct the result.
688040SBaban.Kenkre@Sun.COM */
698040SBaban.Kenkre@Sun.COM buflen = snprintf(NULL, 0, "%s:%s:%u:%u:%s:%s:%s",
708040SBaban.Kenkre@Sun.COM argp->key.name, "x", uid, gid, gecos, homedir, shell) + 1;
718040SBaban.Kenkre@Sun.COM } else {
728040SBaban.Kenkre@Sun.COM if (domain == NULL)
738040SBaban.Kenkre@Sun.COM domain = WK_DOMAIN;
748040SBaban.Kenkre@Sun.COM buflen = snprintf(NULL, 0, "%s@%s:%s:%u:%u:%s:%s:%s",
758040SBaban.Kenkre@Sun.COM name, domain, "x", uid, gid, gecos, homedir, shell) + 1;
768040SBaban.Kenkre@Sun.COM }
778040SBaban.Kenkre@Sun.COM
788040SBaban.Kenkre@Sun.COM
798040SBaban.Kenkre@Sun.COM if (argp->buf.result != NULL) {
808040SBaban.Kenkre@Sun.COM buffer = be->buffer = malloc(buflen);
818040SBaban.Kenkre@Sun.COM if (be->buffer == NULL)
828040SBaban.Kenkre@Sun.COM return (-1);
838040SBaban.Kenkre@Sun.COM be->buflen = buflen;
848040SBaban.Kenkre@Sun.COM } else {
858040SBaban.Kenkre@Sun.COM if (buflen > argp->buf.buflen)
868040SBaban.Kenkre@Sun.COM return (-1);
878040SBaban.Kenkre@Sun.COM buflen = argp->buf.buflen;
888040SBaban.Kenkre@Sun.COM buffer = argp->buf.buffer;
898040SBaban.Kenkre@Sun.COM }
908040SBaban.Kenkre@Sun.COM
918040SBaban.Kenkre@Sun.COM if (be->db_type == NSS_AD_DB_PASSWD_BYNAME)
928040SBaban.Kenkre@Sun.COM (void) snprintf(buffer, buflen, "%s:%s:%u:%u:%s:%s:%s",
938040SBaban.Kenkre@Sun.COM argp->key.name, "x", uid, gid, gecos, homedir, shell);
948040SBaban.Kenkre@Sun.COM else
958040SBaban.Kenkre@Sun.COM (void) snprintf(buffer, buflen, "%s@%s:%s:%u:%u:%s:%s:%s",
968040SBaban.Kenkre@Sun.COM name, domain, "x", uid, gid, gecos, homedir, shell);
978040SBaban.Kenkre@Sun.COM return (0);
988040SBaban.Kenkre@Sun.COM }
998040SBaban.Kenkre@Sun.COM
1008040SBaban.Kenkre@Sun.COM
1018040SBaban.Kenkre@Sun.COM #define NET_SCHEME "/net"
1028040SBaban.Kenkre@Sun.COM
1038040SBaban.Kenkre@Sun.COM /*
1048040SBaban.Kenkre@Sun.COM * 1) If the homeDirectory string is in UNC format then convert it into
1058040SBaban.Kenkre@Sun.COM * a /net format. This needs to be revisited later but is fine for now
1068040SBaban.Kenkre@Sun.COM * because Solaris does not support -hosts automount map for CIFS yet.
1078040SBaban.Kenkre@Sun.COM *
1088040SBaban.Kenkre@Sun.COM * 2) If homeDirectory contains ':' then return NULL because ':' is the
1098040SBaban.Kenkre@Sun.COM * delimiter in passwd entries and may break apps that parse these entries.
1108040SBaban.Kenkre@Sun.COM *
1118040SBaban.Kenkre@Sun.COM * 3) For all other cases return the same string that was passed to
1128040SBaban.Kenkre@Sun.COM * this function.
1138040SBaban.Kenkre@Sun.COM */
1148040SBaban.Kenkre@Sun.COM static
1158040SBaban.Kenkre@Sun.COM char *
process_homedir(char * homedir)1168040SBaban.Kenkre@Sun.COM process_homedir(char *homedir)
1178040SBaban.Kenkre@Sun.COM {
1188040SBaban.Kenkre@Sun.COM size_t len, smb_len;
1198040SBaban.Kenkre@Sun.COM char *smb_homedir;
1208040SBaban.Kenkre@Sun.COM int i, slash = 0;
1218040SBaban.Kenkre@Sun.COM
1228040SBaban.Kenkre@Sun.COM len = strlen(homedir);
1238040SBaban.Kenkre@Sun.COM
1248040SBaban.Kenkre@Sun.COM if (strchr(homedir, ':') != NULL)
1258040SBaban.Kenkre@Sun.COM /*
1268040SBaban.Kenkre@Sun.COM * Ignore paths that have colon ':' because ':' is a
1278040SBaban.Kenkre@Sun.COM * delimiter for the passwd entry.
1288040SBaban.Kenkre@Sun.COM */
1298040SBaban.Kenkre@Sun.COM return (NULL);
1308040SBaban.Kenkre@Sun.COM
1318040SBaban.Kenkre@Sun.COM if (!(len > 1 && homedir[0] == '\\' && homedir[1] == '\\'))
1328040SBaban.Kenkre@Sun.COM /* Keep homedir intact if not in UNC format */
1338040SBaban.Kenkre@Sun.COM return (homedir);
1348040SBaban.Kenkre@Sun.COM
1358040SBaban.Kenkre@Sun.COM /*
1368040SBaban.Kenkre@Sun.COM * Convert UNC string into /net format
1378040SBaban.Kenkre@Sun.COM * Example: \\server\abc -> /net/server/abc
1388040SBaban.Kenkre@Sun.COM */
1398040SBaban.Kenkre@Sun.COM smb_len = len + 1 + sizeof (NET_SCHEME);
1408040SBaban.Kenkre@Sun.COM if ((smb_homedir = calloc(1, smb_len)) == NULL)
1418040SBaban.Kenkre@Sun.COM return (NULL);
1428040SBaban.Kenkre@Sun.COM (void) strlcpy(smb_homedir, NET_SCHEME, smb_len);
1438040SBaban.Kenkre@Sun.COM for (i = strlen(smb_homedir); *homedir != '\0'; homedir++) {
1448040SBaban.Kenkre@Sun.COM if (*homedir == '\\') {
1458040SBaban.Kenkre@Sun.COM /* Reduce double backslashes into one */
1468040SBaban.Kenkre@Sun.COM if (slash)
1478040SBaban.Kenkre@Sun.COM slash = 0;
1488040SBaban.Kenkre@Sun.COM else {
1498040SBaban.Kenkre@Sun.COM slash = 1;
1508040SBaban.Kenkre@Sun.COM smb_homedir[i++] = '/';
1518040SBaban.Kenkre@Sun.COM }
1528040SBaban.Kenkre@Sun.COM } else {
1538040SBaban.Kenkre@Sun.COM smb_homedir[i++] = *homedir;
1548040SBaban.Kenkre@Sun.COM slash = 0;
1558040SBaban.Kenkre@Sun.COM }
1568040SBaban.Kenkre@Sun.COM }
1578040SBaban.Kenkre@Sun.COM return (smb_homedir);
1588040SBaban.Kenkre@Sun.COM }
1598040SBaban.Kenkre@Sun.COM
1608040SBaban.Kenkre@Sun.COM /*
1618040SBaban.Kenkre@Sun.COM * _nss_ad_passwd2str is the data marshaling method for the passwd getXbyY
1628040SBaban.Kenkre@Sun.COM * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
1638040SBaban.Kenkre@Sun.COM * called after a successful AD search has been performed. This method will
1648040SBaban.Kenkre@Sun.COM * parse the AD search values into the file format.
1658040SBaban.Kenkre@Sun.COM * e.g.
1668040SBaban.Kenkre@Sun.COM *
1678040SBaban.Kenkre@Sun.COM * blue@whale:x:123456:10:Blue Whale:/:
1688040SBaban.Kenkre@Sun.COM *
1698040SBaban.Kenkre@Sun.COM */
1708040SBaban.Kenkre@Sun.COM static int
_nss_ad_passwd2str(ad_backend_ptr be,nss_XbyY_args_t * argp)1718040SBaban.Kenkre@Sun.COM _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp)
1728040SBaban.Kenkre@Sun.COM {
1738040SBaban.Kenkre@Sun.COM int nss_result;
1748040SBaban.Kenkre@Sun.COM adutils_result_t *result = be->result;
1758040SBaban.Kenkre@Sun.COM const adutils_entry_t *entry;
1768040SBaban.Kenkre@Sun.COM char **sid_v, *ptr, **pgid_v, *end;
1778040SBaban.Kenkre@Sun.COM ulong_t tmp;
1788040SBaban.Kenkre@Sun.COM uint32_t urid, grid;
1798040SBaban.Kenkre@Sun.COM uid_t uid;
1808040SBaban.Kenkre@Sun.COM gid_t gid;
1818040SBaban.Kenkre@Sun.COM idmap_stat gstat;
1828040SBaban.Kenkre@Sun.COM idmap_get_handle_t *ig = NULL;
1838040SBaban.Kenkre@Sun.COM char **name_v, **dn_v, *domain = NULL;
1848040SBaban.Kenkre@Sun.COM char **gecos_v, **shell_v;
1858040SBaban.Kenkre@Sun.COM char **homedir_v = NULL, *homedir = NULL;
1868040SBaban.Kenkre@Sun.COM char *NULL_STR = "";
1878040SBaban.Kenkre@Sun.COM
1888040SBaban.Kenkre@Sun.COM if (result == NULL)
1898040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_PARSE);
1908040SBaban.Kenkre@Sun.COM entry = adutils_getfirstentry(result);
1918040SBaban.Kenkre@Sun.COM nss_result = NSS_STR_PARSE_PARSE;
1928040SBaban.Kenkre@Sun.COM
1938040SBaban.Kenkre@Sun.COM /* Create handles for idmap service */
194*12914SJoyce.McIntosh@Sun.COM if (idmap_get_create(&ig) != 0)
1958040SBaban.Kenkre@Sun.COM goto result_pwd2str;
1968040SBaban.Kenkre@Sun.COM
1978040SBaban.Kenkre@Sun.COM /* Get name */
1988040SBaban.Kenkre@Sun.COM name_v = adutils_getattr(entry, _PWD_SAN);
1998040SBaban.Kenkre@Sun.COM if (name_v == NULL || name_v[0] == NULL || *name_v[0] == '\0')
2008040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2018040SBaban.Kenkre@Sun.COM
2028040SBaban.Kenkre@Sun.COM /* Get domain */
2038040SBaban.Kenkre@Sun.COM dn_v = adutils_getattr(entry, _PWD_DN);
2048040SBaban.Kenkre@Sun.COM if (dn_v == NULL || dn_v[0] == NULL || *dn_v[0] == '\0')
2058040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2068040SBaban.Kenkre@Sun.COM domain = adutils_dn2dns(dn_v[0]);
2078040SBaban.Kenkre@Sun.COM
2088040SBaban.Kenkre@Sun.COM /* Get objectSID (in text format) */
2098040SBaban.Kenkre@Sun.COM sid_v = adutils_getattr(entry, _PWD_OBJSID);
2108040SBaban.Kenkre@Sun.COM if (sid_v == NULL || sid_v[0] == NULL || *sid_v[0] == '\0')
2118040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2128040SBaban.Kenkre@Sun.COM
2138040SBaban.Kenkre@Sun.COM /* Break SID into prefix and rid */
2148040SBaban.Kenkre@Sun.COM if ((ptr = strrchr(sid_v[0], '-')) == NULL)
2158040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2168040SBaban.Kenkre@Sun.COM *ptr = '\0';
2178040SBaban.Kenkre@Sun.COM end = ++ptr;
2188040SBaban.Kenkre@Sun.COM tmp = strtoul(ptr, &end, 10);
2198040SBaban.Kenkre@Sun.COM if (end == ptr || tmp > UINT32_MAX)
2208040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2218040SBaban.Kenkre@Sun.COM urid = (uint32_t)tmp;
2228040SBaban.Kenkre@Sun.COM
2238040SBaban.Kenkre@Sun.COM /* We already have uid -- no need to call idmapd */
2248040SBaban.Kenkre@Sun.COM if (be->db_type == NSS_AD_DB_PASSWD_BYUID)
2258040SBaban.Kenkre@Sun.COM uid = argp->key.uid;
2268040SBaban.Kenkre@Sun.COM else
2278040SBaban.Kenkre@Sun.COM uid = be->uid;
2288040SBaban.Kenkre@Sun.COM
2298040SBaban.Kenkre@Sun.COM /* Get primaryGroupID */
2308040SBaban.Kenkre@Sun.COM pgid_v = adutils_getattr(entry, _PWD_PRIMARYGROUPID);
2318040SBaban.Kenkre@Sun.COM if (pgid_v == NULL || pgid_v[0] == NULL || *pgid_v[0] == '\0')
2328040SBaban.Kenkre@Sun.COM /*
2338040SBaban.Kenkre@Sun.COM * If primaryGroupID is not found then we request
2348040SBaban.Kenkre@Sun.COM * a GID to be mapped to the given user's objectSID
2358040SBaban.Kenkre@Sun.COM * (diagonal mapping) and use this GID as the primary
2368040SBaban.Kenkre@Sun.COM * GID for the entry.
2378040SBaban.Kenkre@Sun.COM */
2388040SBaban.Kenkre@Sun.COM grid = urid;
2398040SBaban.Kenkre@Sun.COM else {
2408040SBaban.Kenkre@Sun.COM end = pgid_v[0];
2418040SBaban.Kenkre@Sun.COM tmp = strtoul(pgid_v[0], &end, 10);
2428040SBaban.Kenkre@Sun.COM if (end == pgid_v[0] || tmp > UINT32_MAX)
2438040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2448040SBaban.Kenkre@Sun.COM grid = (uint32_t)tmp;
2458040SBaban.Kenkre@Sun.COM }
2468040SBaban.Kenkre@Sun.COM
2478040SBaban.Kenkre@Sun.COM /* Map group SID to GID using idmap service */
2488040SBaban.Kenkre@Sun.COM if (idmap_get_gidbysid(ig, sid_v[0], grid, 0, &gid, &gstat) != 0)
2498040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2508040SBaban.Kenkre@Sun.COM if (idmap_get_mappings(ig) != 0 || gstat != 0) {
2518040SBaban.Kenkre@Sun.COM RESET_ERRNO();
2528040SBaban.Kenkre@Sun.COM goto result_pwd2str;
2538040SBaban.Kenkre@Sun.COM }
2548040SBaban.Kenkre@Sun.COM
2558040SBaban.Kenkre@Sun.COM /* Get gecos, homedirectory and shell information if available */
2568040SBaban.Kenkre@Sun.COM gecos_v = adutils_getattr(entry, _PWD_CN);
2578040SBaban.Kenkre@Sun.COM if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
2588040SBaban.Kenkre@Sun.COM gecos_v = &NULL_STR;
2598040SBaban.Kenkre@Sun.COM
2608040SBaban.Kenkre@Sun.COM homedir_v = adutils_getattr(entry, _PWD_HOMEDIRECTORY);
2618040SBaban.Kenkre@Sun.COM if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
2628040SBaban.Kenkre@Sun.COM homedir = NULL_STR;
2638040SBaban.Kenkre@Sun.COM else if ((homedir = process_homedir(homedir_v[0])) == NULL)
2648040SBaban.Kenkre@Sun.COM homedir = NULL_STR;
2658040SBaban.Kenkre@Sun.COM
2668040SBaban.Kenkre@Sun.COM shell_v = adutils_getattr(entry, _PWD_LOGINSHELL);
2678040SBaban.Kenkre@Sun.COM if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
2688040SBaban.Kenkre@Sun.COM shell_v = &NULL_STR;
2698040SBaban.Kenkre@Sun.COM
2708040SBaban.Kenkre@Sun.COM if (update_buffer(be, argp, name_v[0], domain, uid, gid,
2718040SBaban.Kenkre@Sun.COM gecos_v[0], homedir, shell_v[0]) < 0)
2728040SBaban.Kenkre@Sun.COM nss_result = NSS_STR_PARSE_ERANGE;
2738040SBaban.Kenkre@Sun.COM else
2748040SBaban.Kenkre@Sun.COM nss_result = NSS_STR_PARSE_SUCCESS;
2758040SBaban.Kenkre@Sun.COM
2768040SBaban.Kenkre@Sun.COM result_pwd2str:
2778040SBaban.Kenkre@Sun.COM idmap_get_destroy(ig);
2788040SBaban.Kenkre@Sun.COM (void) adutils_freeresult(&be->result);
2798040SBaban.Kenkre@Sun.COM free(domain);
2808040SBaban.Kenkre@Sun.COM if (homedir != NULL_STR && homedir_v != NULL &&
2818040SBaban.Kenkre@Sun.COM homedir != homedir_v[0])
2828040SBaban.Kenkre@Sun.COM free(homedir);
2838040SBaban.Kenkre@Sun.COM return ((int)nss_result);
2848040SBaban.Kenkre@Sun.COM }
2858040SBaban.Kenkre@Sun.COM
2868040SBaban.Kenkre@Sun.COM /*
2878040SBaban.Kenkre@Sun.COM * getbyname gets a passwd entry by winname. This function constructs an ldap
2888040SBaban.Kenkre@Sun.COM * search filter using the name invocation parameter and the getpwnam search
2898040SBaban.Kenkre@Sun.COM * filter defined. Once the filter is constructed, we search for a matching
2908040SBaban.Kenkre@Sun.COM * entry and marshal the data results into struct passwd for the frontend
2918040SBaban.Kenkre@Sun.COM * process. The function _nss_ad_passwd2ent performs the data marshaling.
2928040SBaban.Kenkre@Sun.COM */
2938040SBaban.Kenkre@Sun.COM
2948040SBaban.Kenkre@Sun.COM static nss_status_t
getbyname(ad_backend_ptr be,void * a)2958040SBaban.Kenkre@Sun.COM getbyname(ad_backend_ptr be, void *a)
2968040SBaban.Kenkre@Sun.COM {
2978040SBaban.Kenkre@Sun.COM nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2988040SBaban.Kenkre@Sun.COM char *searchfilter;
2998040SBaban.Kenkre@Sun.COM char name[SEARCHFILTERLEN];
3008040SBaban.Kenkre@Sun.COM char *dname;
3018040SBaban.Kenkre@Sun.COM int filterlen, namelen;
3028040SBaban.Kenkre@Sun.COM int flag;
3038040SBaban.Kenkre@Sun.COM nss_status_t stat;
3048040SBaban.Kenkre@Sun.COM idmap_stat idmaprc;
3058040SBaban.Kenkre@Sun.COM uid_t uid;
3068040SBaban.Kenkre@Sun.COM gid_t gid;
3078040SBaban.Kenkre@Sun.COM int is_user, is_wuser, try_idmap;
3088040SBaban.Kenkre@Sun.COM
3098040SBaban.Kenkre@Sun.COM be->db_type = NSS_AD_DB_PASSWD_BYNAME;
3108040SBaban.Kenkre@Sun.COM
3118040SBaban.Kenkre@Sun.COM /* Sanitize name so that it can be used in our LDAP filter */
3128040SBaban.Kenkre@Sun.COM if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
3138040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
3148040SBaban.Kenkre@Sun.COM
3158040SBaban.Kenkre@Sun.COM if ((dname = strchr(name, '@')) == NULL)
3168040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
3178040SBaban.Kenkre@Sun.COM
3188040SBaban.Kenkre@Sun.COM *dname = '\0';
3198040SBaban.Kenkre@Sun.COM dname++;
3208040SBaban.Kenkre@Sun.COM
3218040SBaban.Kenkre@Sun.COM /*
3228040SBaban.Kenkre@Sun.COM * Map the given name to UID using idmap service. If idmap
3238040SBaban.Kenkre@Sun.COM * call fails then this will save us doing AD discovery and
3248040SBaban.Kenkre@Sun.COM * AD lookup here.
3258040SBaban.Kenkre@Sun.COM */
3268040SBaban.Kenkre@Sun.COM flag = (strcasecmp(dname, WK_DOMAIN) == 0) ?
3278040SBaban.Kenkre@Sun.COM IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0;
3288040SBaban.Kenkre@Sun.COM is_wuser = -1;
3298040SBaban.Kenkre@Sun.COM is_user = 1;
330*12914SJoyce.McIntosh@Sun.COM if (idmap_get_w2u_mapping(NULL, NULL, name,
3318040SBaban.Kenkre@Sun.COM dname, flag, &is_user, &is_wuser, &be->uid, NULL,
3328040SBaban.Kenkre@Sun.COM NULL, NULL) != IDMAP_SUCCESS) {
3338040SBaban.Kenkre@Sun.COM RESET_ERRNO();
3348040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
3358040SBaban.Kenkre@Sun.COM }
3368040SBaban.Kenkre@Sun.COM
3378040SBaban.Kenkre@Sun.COM /* If this is not a Well-Known SID then try AD lookup. */
3388040SBaban.Kenkre@Sun.COM if (strcasecmp(dname, WK_DOMAIN) != 0) {
3398040SBaban.Kenkre@Sun.COM /* Assemble filter using the given name */
3408040SBaban.Kenkre@Sun.COM namelen = strlen(name);
3418040SBaban.Kenkre@Sun.COM filterlen = snprintf(NULL, 0, _F_GETPWNAM, namelen, name) + 1;
3428040SBaban.Kenkre@Sun.COM if ((searchfilter = (char *)malloc(filterlen)) == NULL)
3438040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
3448040SBaban.Kenkre@Sun.COM (void) snprintf(searchfilter, filterlen, _F_GETPWNAM,
3458040SBaban.Kenkre@Sun.COM namelen, name);
3468040SBaban.Kenkre@Sun.COM stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
3478040SBaban.Kenkre@Sun.COM dname, &try_idmap);
3488040SBaban.Kenkre@Sun.COM free(searchfilter);
3498040SBaban.Kenkre@Sun.COM
350*12914SJoyce.McIntosh@Sun.COM if (!try_idmap)
3518040SBaban.Kenkre@Sun.COM return (stat);
3528040SBaban.Kenkre@Sun.COM
3538040SBaban.Kenkre@Sun.COM }
3548040SBaban.Kenkre@Sun.COM
3558040SBaban.Kenkre@Sun.COM /*
3568040SBaban.Kenkre@Sun.COM * Either this is a Well-Known SID or AD lookup failed. Map
3578040SBaban.Kenkre@Sun.COM * the given name to GID using idmap service and construct
3588040SBaban.Kenkre@Sun.COM * the passwd entry.
3598040SBaban.Kenkre@Sun.COM */
3608040SBaban.Kenkre@Sun.COM is_wuser = -1;
3618040SBaban.Kenkre@Sun.COM is_user = 0; /* Map name to primary gid */
362*12914SJoyce.McIntosh@Sun.COM idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
3638040SBaban.Kenkre@Sun.COM flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL);
3648040SBaban.Kenkre@Sun.COM if (idmaprc != IDMAP_SUCCESS) {
3658040SBaban.Kenkre@Sun.COM RESET_ERRNO();
3668040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
3678040SBaban.Kenkre@Sun.COM }
3688040SBaban.Kenkre@Sun.COM
3698040SBaban.Kenkre@Sun.COM /* Create passwd(4) style string */
3708040SBaban.Kenkre@Sun.COM if (update_buffer(be, argp, name, dname,
3718040SBaban.Kenkre@Sun.COM be->uid, gid, "", "", "") < 0)
3728040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND);
3738040SBaban.Kenkre@Sun.COM
3748040SBaban.Kenkre@Sun.COM /* Marshall the data, sanitize the return status and return */
3758040SBaban.Kenkre@Sun.COM stat = _nss_ad_marshall_data(be, argp);
3768040SBaban.Kenkre@Sun.COM return (_nss_ad_sanitize_status(be, argp, stat));
3778040SBaban.Kenkre@Sun.COM }
3788040SBaban.Kenkre@Sun.COM
3798040SBaban.Kenkre@Sun.COM
3808040SBaban.Kenkre@Sun.COM /*
3818040SBaban.Kenkre@Sun.COM * getbyuid gets a passwd entry by uid number. This function constructs an ldap
3828040SBaban.Kenkre@Sun.COM * search filter using the uid invocation parameter and the getpwuid search
3838040SBaban.Kenkre@Sun.COM * filter defined. Once the filter is constructed, we search for a matching
3848040SBaban.Kenkre@Sun.COM * entry and marshal the data results into struct passwd for the frontend
3858040SBaban.Kenkre@Sun.COM * process. The function _nss_ad_passwd2ent performs the data marshaling.
3868040SBaban.Kenkre@Sun.COM */
3878040SBaban.Kenkre@Sun.COM
3888040SBaban.Kenkre@Sun.COM static nss_status_t
getbyuid(ad_backend_ptr be,void * a)3898040SBaban.Kenkre@Sun.COM getbyuid(ad_backend_ptr be, void *a)
3908040SBaban.Kenkre@Sun.COM {
3918040SBaban.Kenkre@Sun.COM nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
3928040SBaban.Kenkre@Sun.COM char searchfilter[ADUTILS_MAXHEXBINSID + 14];
3938040SBaban.Kenkre@Sun.COM char *sidprefix = NULL;
3948040SBaban.Kenkre@Sun.COM idmap_rid_t rid;
3958040SBaban.Kenkre@Sun.COM char cbinsid[ADUTILS_MAXHEXBINSID + 1];
3968040SBaban.Kenkre@Sun.COM char *winname = NULL, *windomain = NULL;
3978040SBaban.Kenkre@Sun.COM int is_user, is_wuser;
3988040SBaban.Kenkre@Sun.COM gid_t gid;
3998040SBaban.Kenkre@Sun.COM idmap_stat idmaprc;
4008040SBaban.Kenkre@Sun.COM int ret, try_idmap;
4018040SBaban.Kenkre@Sun.COM nss_status_t stat;
4028040SBaban.Kenkre@Sun.COM
4038040SBaban.Kenkre@Sun.COM be->db_type = NSS_AD_DB_PASSWD_BYUID;
4048040SBaban.Kenkre@Sun.COM
4058040SBaban.Kenkre@Sun.COM stat = (nss_status_t)NSS_NOTFOUND;
4068040SBaban.Kenkre@Sun.COM
4078040SBaban.Kenkre@Sun.COM /* nss_ad does not support non ephemeral uids */
4088040SBaban.Kenkre@Sun.COM if (argp->key.uid <= MAXUID)
4098040SBaban.Kenkre@Sun.COM goto out;
4108040SBaban.Kenkre@Sun.COM
4118040SBaban.Kenkre@Sun.COM /* Map the given UID to a SID using the idmap service */
412*12914SJoyce.McIntosh@Sun.COM if (idmap_get_u2w_mapping(&argp->key.uid, NULL, 0,
4138040SBaban.Kenkre@Sun.COM 1, NULL, &sidprefix, &rid, &winname, &windomain,
4148040SBaban.Kenkre@Sun.COM NULL, NULL) != 0) {
4158040SBaban.Kenkre@Sun.COM RESET_ERRNO();
4168040SBaban.Kenkre@Sun.COM goto out;
4178040SBaban.Kenkre@Sun.COM }
4188040SBaban.Kenkre@Sun.COM
4198040SBaban.Kenkre@Sun.COM /*
4208040SBaban.Kenkre@Sun.COM * NULL winname implies a local SID or unresolvable SID both of
4218040SBaban.Kenkre@Sun.COM * which cannot be used to generated passwd(4) entry
4228040SBaban.Kenkre@Sun.COM */
4238040SBaban.Kenkre@Sun.COM if (winname == NULL)
4248040SBaban.Kenkre@Sun.COM goto out;
4258040SBaban.Kenkre@Sun.COM
4268040SBaban.Kenkre@Sun.COM /* If this is not a Well-Known SID try AD lookup */
4278040SBaban.Kenkre@Sun.COM if (windomain != NULL && strcasecmp(windomain, WK_DOMAIN) != 0) {
4288040SBaban.Kenkre@Sun.COM if (adutils_txtsid2hexbinsid(sidprefix, &rid,
4298040SBaban.Kenkre@Sun.COM &cbinsid[0], sizeof (cbinsid)) != 0)
4308040SBaban.Kenkre@Sun.COM goto out;
4318040SBaban.Kenkre@Sun.COM
4328040SBaban.Kenkre@Sun.COM ret = snprintf(searchfilter, sizeof (searchfilter),
4338040SBaban.Kenkre@Sun.COM _F_GETPWUID, cbinsid);
4348040SBaban.Kenkre@Sun.COM if (ret >= sizeof (searchfilter) || ret < 0)
4358040SBaban.Kenkre@Sun.COM goto out;
4368040SBaban.Kenkre@Sun.COM
4378040SBaban.Kenkre@Sun.COM stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
4388040SBaban.Kenkre@Sun.COM windomain, &try_idmap);
4398040SBaban.Kenkre@Sun.COM
4408040SBaban.Kenkre@Sun.COM if (!try_idmap)
4418040SBaban.Kenkre@Sun.COM goto out;
4428040SBaban.Kenkre@Sun.COM }
4438040SBaban.Kenkre@Sun.COM
4448040SBaban.Kenkre@Sun.COM /* Map winname to primary gid using idmap service */
4458040SBaban.Kenkre@Sun.COM is_user = 0;
4468040SBaban.Kenkre@Sun.COM is_wuser = -1;
447*12914SJoyce.McIntosh@Sun.COM idmaprc = idmap_get_w2u_mapping(NULL, NULL,
4488040SBaban.Kenkre@Sun.COM winname, windomain, 0, &is_user, &is_wuser, &gid,
4498040SBaban.Kenkre@Sun.COM NULL, NULL, NULL);
4508040SBaban.Kenkre@Sun.COM
4518040SBaban.Kenkre@Sun.COM if (idmaprc != IDMAP_SUCCESS) {
4528040SBaban.Kenkre@Sun.COM RESET_ERRNO();
4538040SBaban.Kenkre@Sun.COM goto out;
4548040SBaban.Kenkre@Sun.COM }
4558040SBaban.Kenkre@Sun.COM
4568040SBaban.Kenkre@Sun.COM /* Create passwd(4) style string */
4578040SBaban.Kenkre@Sun.COM if (update_buffer(be, argp, winname, windomain,
4588040SBaban.Kenkre@Sun.COM argp->key.uid, gid, "", "", "") < 0)
4598040SBaban.Kenkre@Sun.COM goto out;
4608040SBaban.Kenkre@Sun.COM
4618040SBaban.Kenkre@Sun.COM /* Marshall the data, sanitize the return status and return */
4628040SBaban.Kenkre@Sun.COM stat = _nss_ad_marshall_data(be, argp);
4638040SBaban.Kenkre@Sun.COM stat = _nss_ad_sanitize_status(be, argp, stat);
4648040SBaban.Kenkre@Sun.COM
4658040SBaban.Kenkre@Sun.COM out:
4668040SBaban.Kenkre@Sun.COM idmap_free(sidprefix);
4678040SBaban.Kenkre@Sun.COM idmap_free(winname);
4688040SBaban.Kenkre@Sun.COM idmap_free(windomain);
4698040SBaban.Kenkre@Sun.COM return (stat);
4708040SBaban.Kenkre@Sun.COM }
4718040SBaban.Kenkre@Sun.COM
4728040SBaban.Kenkre@Sun.COM static ad_backend_op_t passwd_ops[] = {
4738040SBaban.Kenkre@Sun.COM _nss_ad_destr,
4748040SBaban.Kenkre@Sun.COM _nss_ad_endent,
4758040SBaban.Kenkre@Sun.COM _nss_ad_setent,
4768040SBaban.Kenkre@Sun.COM _nss_ad_getent,
4778040SBaban.Kenkre@Sun.COM getbyname,
4788040SBaban.Kenkre@Sun.COM getbyuid
4798040SBaban.Kenkre@Sun.COM };
4808040SBaban.Kenkre@Sun.COM
4818040SBaban.Kenkre@Sun.COM /*
4828040SBaban.Kenkre@Sun.COM * _nss_ad_passwd_constr is where life begins. This function calls the
4838040SBaban.Kenkre@Sun.COM * generic AD constructor function to define and build the abstract
4848040SBaban.Kenkre@Sun.COM * data types required to support AD operations.
4858040SBaban.Kenkre@Sun.COM */
4868040SBaban.Kenkre@Sun.COM
4878040SBaban.Kenkre@Sun.COM /*ARGSUSED0*/
4888040SBaban.Kenkre@Sun.COM nss_backend_t *
_nss_ad_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)4898040SBaban.Kenkre@Sun.COM _nss_ad_passwd_constr(const char *dummy1, const char *dummy2,
4908040SBaban.Kenkre@Sun.COM const char *dummy3)
4918040SBaban.Kenkre@Sun.COM {
4928040SBaban.Kenkre@Sun.COM
4938040SBaban.Kenkre@Sun.COM return ((nss_backend_t *)_nss_ad_constr(passwd_ops,
4948040SBaban.Kenkre@Sun.COM sizeof (passwd_ops)/sizeof (passwd_ops[0]),
4958040SBaban.Kenkre@Sun.COM _PASSWD, pwd_attrs, _nss_ad_passwd2str));
4968040SBaban.Kenkre@Sun.COM }
497