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 <shadow.h> 27 #include <stdlib.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) 33 { 34 int buflen; 35 char *buffer; 36 37 /* 38 * The user password is not available in the AD object and therefore 39 * sp_pwdp will be "*NP*". 40 * 41 * nss_ad will leave aging fields empty (i.e. The front end 42 * marshaller will set sp_lstchgst, sp_min, sp_max, sp_warn, 43 * sp_inact, and sp_expire to -1 and sp_flag to 0) because shadow 44 * fields are irrevalent with AD and krb5. 45 */ 46 47 buflen = snprintf(NULL, 0, "%s@%s:*NP*:::::::", name, domain) + 1; 48 49 if (argp->buf.result != NULL) { 50 buffer = be->buffer = malloc(buflen); 51 if (be->buffer == NULL) 52 return (-1); 53 be->buflen = buflen; 54 } else { 55 if (buflen > argp->buf.buflen) 56 return (-1); 57 buflen = argp->buf.buflen; 58 buffer = argp->buf.buffer; 59 } 60 61 buflen = snprintf(buffer, buflen, "%s@%s:*NP*:::::::", 62 name, domain) + 1; 63 return (0); 64 } 65 66 /* 67 * getbynam gets a shadow entry by winname. This function constructs an ldap 68 * search filter using the name invocation parameter and the getspnam search 69 * filter defined. Once the filter is constructed we search for a matching 70 * entry and marshal the data results into struct shadow for the frontend 71 * process. The function _nss_ad_shadow2ent performs the data marshaling. 72 */ 73 static nss_status_t 74 getbynam(ad_backend_ptr be, void *a) 75 { 76 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 77 char name[SEARCHFILTERLEN + 1]; 78 char *dname; 79 nss_status_t stat; 80 idmap_stat idmaprc; 81 uid_t uid; 82 int is_user, is_wuser; 83 idmap_handle_t *ih; 84 85 be->db_type = NSS_AD_DB_SHADOW_BYNAME; 86 87 /* Sanitize name so that it can be used in our LDAP filter */ 88 if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 89 return ((nss_status_t)NSS_NOTFOUND); 90 91 if ((dname = strchr(name, '@')) == NULL) 92 return ((nss_status_t)NSS_NOTFOUND); 93 94 *dname = '\0'; 95 dname++; 96 97 /* 98 * Use idmap service to verify that the given 99 * name is a valid Windows name. 100 */ 101 idmaprc = idmap_init(&ih); 102 if (idmaprc != IDMAP_SUCCESS) 103 return ((nss_status_t)NSS_NOTFOUND); 104 is_wuser = -1; 105 is_user = 1; 106 idmaprc = idmap_get_w2u_mapping(ih, NULL, NULL, name, dname, 107 0, &is_user, &is_wuser, &uid, NULL, NULL, NULL); 108 (void) idmap_fini(ih); 109 if (idmaprc != IDMAP_SUCCESS) { 110 RESET_ERRNO(); 111 return ((nss_status_t)NSS_NOTFOUND); 112 } 113 114 /* Create shadow(4) style string */ 115 if (update_buffer(be, argp, name, dname) < 0) 116 return ((nss_status_t)NSS_NOTFOUND); 117 118 /* Marshall the data, sanitize the return status and return */ 119 stat = _nss_ad_marshall_data(be, argp); 120 return (_nss_ad_sanitize_status(be, argp, stat)); 121 } 122 123 static ad_backend_op_t sp_ops[] = { 124 _nss_ad_destr, 125 _nss_ad_endent, 126 _nss_ad_setent, 127 _nss_ad_getent, 128 getbynam 129 }; 130 131 132 /* 133 * _nss_ad_passwd_constr is where life begins. This function calls the 134 * generic ldap constructor function to define and build the abstract 135 * data types required to support ldap operations. 136 */ 137 /*ARGSUSED0*/ 138 nss_backend_t * 139 _nss_ad_shadow_constr(const char *dummy1, const char *dummy2, 140 const char *dummy3) 141 { 142 143 return ((nss_backend_t *)_nss_ad_constr(sp_ops, 144 sizeof (sp_ops)/sizeof (sp_ops[0]), 145 _SHADOW, NULL, NULL)); 146 } 147