1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <grp.h> 27 #include <idmap.h> 28 #include "ad_common.h" 29 30 static int 31 update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp, 32 const char *name, const char *domain, gid_t gid) 33 { 34 int buflen; 35 char *buffer; 36 37 if (domain == NULL) 38 domain = WK_DOMAIN; 39 40 buflen = snprintf(NULL, 0, "%s@%s::%u:", name, domain, gid) + 1; 41 42 if (argp->buf.result != NULL) { 43 buffer = be->buffer = malloc(buflen); 44 if (be->buffer == NULL) 45 return (-1); 46 be->buflen = buflen; 47 } else { 48 if (buflen > argp->buf.buflen) 49 return (-1); 50 buflen = argp->buf.buflen; 51 buffer = argp->buf.buffer; 52 } 53 54 (void) snprintf(buffer, buflen, "%s@%s::%u:", name, domain, gid); 55 return (0); 56 } 57 58 /* 59 * getbynam gets a group entry by name. This function constructs an ldap 60 * search filter using the name invocation parameter and the getgrnam search 61 * filter defined. Once the filter is constructed, we search for a matching 62 * entry and marshal the data results into struct group for the frontend 63 * process. The function _nss_ad_group2ent performs the data marshaling. 64 */ 65 static nss_status_t 66 getbynam(ad_backend_ptr be, void *a) 67 { 68 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 69 char name[SEARCHFILTERLEN]; 70 char *dname; 71 nss_status_t stat; 72 idmap_stat idmaprc; 73 gid_t gid; 74 int is_user, is_wuser; 75 idmap_handle_t *ih; 76 77 be->db_type = NSS_AD_DB_GROUP_BYNAME; 78 79 /* Sanitize name so that it can be used in our LDAP filter */ 80 if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 81 return ((nss_status_t)NSS_NOTFOUND); 82 83 if ((dname = strchr(name, '@')) == NULL) 84 return ((nss_status_t)NSS_NOTFOUND); 85 86 *dname = '\0'; 87 dname++; 88 89 /* 90 * Map the name to gid using idmap service. 91 */ 92 idmaprc = idmap_init(&ih); 93 if (idmaprc != IDMAP_SUCCESS) 94 return ((nss_status_t)NSS_NOTFOUND); 95 is_wuser = -1; 96 is_user = 0; /* Map name to gid */ 97 idmaprc = idmap_get_w2u_mapping(ih, NULL, NULL, name, dname, 98 0, &is_user, &is_wuser, &gid, NULL, NULL, NULL); 99 (void) idmap_fini(ih); 100 if (idmaprc != IDMAP_SUCCESS) { 101 RESET_ERRNO(); 102 return ((nss_status_t)NSS_NOTFOUND); 103 } 104 105 /* Create group(4) style string */ 106 if (update_buffer(be, argp, name, dname, gid) < 0) 107 return ((nss_status_t)NSS_NOTFOUND); 108 109 /* Marshall the data, sanitize the return status and return */ 110 stat = _nss_ad_marshall_data(be, argp); 111 return (_nss_ad_sanitize_status(be, argp, stat)); 112 } 113 114 /* 115 * getbygid gets a group entry by number. This function constructs an ldap 116 * search filter using the name invocation parameter and the getgrgid search 117 * filter defined. Once the filter is constructed, we searche for a matching 118 * entry and marshal the data results into struct group for the frontend 119 * process. The function _nss_ad_group2ent performs the data marshaling. 120 */ 121 static nss_status_t 122 getbygid(ad_backend_ptr be, void *a) 123 { 124 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 125 char *winname = NULL, *windomain = NULL; 126 nss_status_t stat; 127 128 be->db_type = NSS_AD_DB_GROUP_BYGID; 129 130 stat = (nss_status_t)NSS_NOTFOUND; 131 132 /* nss_ad does not support non ephemeral gids */ 133 if (argp->key.gid <= MAXUID) 134 goto out; 135 136 /* Map the given GID to a SID using the idmap service */ 137 if (idmap_init(&be->ih) != 0) 138 goto out; 139 if (idmap_get_u2w_mapping(be->ih, &argp->key.gid, NULL, 0, 140 0, NULL, NULL, NULL, &winname, &windomain, 141 NULL, NULL) != 0) { 142 RESET_ERRNO(); 143 goto out; 144 } 145 146 /* 147 * NULL winname implies a local SID or unresolvable SID both of 148 * which cannot be used to generated group(4) entry 149 */ 150 if (winname == NULL) 151 goto out; 152 153 /* Create group(4) style string */ 154 if (update_buffer(be, argp, winname, windomain, argp->key.gid) < 0) 155 goto out; 156 157 /* Marshall the data, sanitize the return status and return */ 158 stat = _nss_ad_marshall_data(be, argp); 159 stat = _nss_ad_sanitize_status(be, argp, stat); 160 161 out: 162 idmap_free(winname); 163 idmap_free(windomain); 164 (void) idmap_fini(be->ih); 165 be->ih = NULL; 166 return (stat); 167 } 168 169 static ad_backend_op_t gr_ops[] = { 170 _nss_ad_destr, 171 _nss_ad_endent, 172 _nss_ad_setent, 173 _nss_ad_getent, 174 getbynam, 175 getbygid 176 }; 177 178 /*ARGSUSED0*/ 179 nss_backend_t * 180 _nss_ad_group_constr(const char *dummy1, const char *dummy2, 181 const char *dummy3) 182 { 183 184 return ((nss_backend_t *)_nss_ad_constr(gr_ops, 185 sizeof (gr_ops)/sizeof (gr_ops[0]), _GROUP, NULL, NULL)); 186 } 187