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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <grp.h> 26 #include <idmap.h> 27 #include "ad_common.h" 28 29 static int 30 update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp, 31 const char *name, const char *domain, gid_t gid) 32 { 33 int buflen; 34 char *buffer; 35 36 if (domain == NULL) 37 domain = WK_DOMAIN; 38 39 buflen = snprintf(NULL, 0, "%s@%s::%u:", name, domain, gid) + 1; 40 41 if (argp->buf.result != NULL) { 42 buffer = be->buffer = malloc(buflen); 43 if (be->buffer == NULL) 44 return (-1); 45 be->buflen = buflen; 46 } else { 47 if (buflen > argp->buf.buflen) 48 return (-1); 49 buflen = argp->buf.buflen; 50 buffer = argp->buf.buffer; 51 } 52 53 (void) snprintf(buffer, buflen, "%s@%s::%u:", name, domain, gid); 54 return (0); 55 } 56 57 /* 58 * getbynam gets a group entry by name. This function constructs an ldap 59 * search filter using the name invocation parameter and the getgrnam search 60 * filter defined. Once the filter is constructed, we search for a matching 61 * entry and marshal the data results into struct group for the frontend 62 * process. The function _nss_ad_group2ent performs the data marshaling. 63 */ 64 static nss_status_t 65 getbynam(ad_backend_ptr be, void *a) 66 { 67 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 68 char name[SEARCHFILTERLEN]; 69 char *dname; 70 nss_status_t stat; 71 idmap_stat idmaprc; 72 gid_t gid; 73 int is_user, is_wuser; 74 75 be->db_type = NSS_AD_DB_GROUP_BYNAME; 76 77 /* Sanitize name so that it can be used in our LDAP filter */ 78 if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 79 return ((nss_status_t)NSS_NOTFOUND); 80 81 if ((dname = strchr(name, '@')) == NULL) 82 return ((nss_status_t)NSS_NOTFOUND); 83 84 *dname = '\0'; 85 dname++; 86 87 /* 88 * Map the name to gid using idmap service. 89 */ 90 is_wuser = -1; 91 is_user = 0; /* Map name to gid */ 92 idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname, 93 0, &is_user, &is_wuser, &gid, NULL, NULL, NULL); 94 if (idmaprc != IDMAP_SUCCESS) { 95 RESET_ERRNO(); 96 return ((nss_status_t)NSS_NOTFOUND); 97 } 98 99 /* Create group(5) style string */ 100 if (update_buffer(be, argp, name, dname, gid) < 0) 101 return ((nss_status_t)NSS_NOTFOUND); 102 103 /* Marshall the data, sanitize the return status and return */ 104 stat = _nss_ad_marshall_data(be, argp); 105 return (_nss_ad_sanitize_status(be, argp, stat)); 106 } 107 108 /* 109 * getbygid gets a group entry by number. This function constructs an ldap 110 * search filter using the name invocation parameter and the getgrgid search 111 * filter defined. Once the filter is constructed, we searche for a matching 112 * entry and marshal the data results into struct group for the frontend 113 * process. The function _nss_ad_group2ent performs the data marshaling. 114 */ 115 static nss_status_t 116 getbygid(ad_backend_ptr be, void *a) 117 { 118 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 119 char *winname = NULL, *windomain = NULL; 120 nss_status_t stat; 121 122 be->db_type = NSS_AD_DB_GROUP_BYGID; 123 124 stat = (nss_status_t)NSS_NOTFOUND; 125 126 /* nss_ad does not support non ephemeral gids */ 127 if (argp->key.gid <= MAXUID) 128 goto out; 129 130 /* Map the given GID to a SID using the idmap service */ 131 if (idmap_get_u2w_mapping(&argp->key.gid, NULL, 0, 132 0, NULL, NULL, NULL, &winname, &windomain, 133 NULL, NULL) != 0) { 134 RESET_ERRNO(); 135 goto out; 136 } 137 138 /* 139 * NULL winname implies a local SID or unresolvable SID both of 140 * which cannot be used to generated group(5) entry 141 */ 142 if (winname == NULL) 143 goto out; 144 145 /* Create group(5) style string */ 146 if (update_buffer(be, argp, winname, windomain, argp->key.gid) < 0) 147 goto out; 148 149 /* Marshall the data, sanitize the return status and return */ 150 stat = _nss_ad_marshall_data(be, argp); 151 stat = _nss_ad_sanitize_status(be, argp, stat); 152 153 out: 154 idmap_free(winname); 155 idmap_free(windomain); 156 return (stat); 157 } 158 159 static ad_backend_op_t gr_ops[] = { 160 _nss_ad_destr, 161 _nss_ad_endent, 162 _nss_ad_setent, 163 _nss_ad_getent, 164 getbynam, 165 getbygid 166 }; 167 168 /*ARGSUSED0*/ 169 nss_backend_t * 170 _nss_ad_group_constr(const char *dummy1, const char *dummy2, 171 const char *dummy3) 172 { 173 174 return ((nss_backend_t *)_nss_ad_constr(gr_ops, 175 sizeof (gr_ops)/sizeof (gr_ops[0]), _GROUP, NULL, NULL)); 176 } 177