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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Door calls invoked by CLIs to obtain various SMB door service provided 28 * by SMB daemon. 29 */ 30 31 #include <fcntl.h> 32 #include <syslog.h> 33 #include <string.h> 34 #include <strings.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <assert.h> 38 #include <smbsrv/libsmb.h> 39 #include <smbsrv/wintypes.h> 40 #include <smbsrv/smb_door_svc.h> 41 #include <smbsrv/smb_common_door.h> 42 43 /* 44 * Given a SID, make a door call to get the associated name. 45 * 46 * Returns 0 if the door call is successful, otherwise -1. 47 * 48 * If 0 is returned, the lookup result will be available in a_status. 49 * NT_STATUS_SUCCESS The SID was mapped to a name. 50 * NT_STATUS_NONE_MAPPED The SID could not be mapped to a name. 51 */ 52 int 53 smb_lookup_sid(const char *sid, lsa_account_t *acct) 54 { 55 door_arg_t arg; 56 char *buf; 57 size_t len; 58 int opcode = SMB_DR_LOOKUP_SID; 59 int fd; 60 int rc; 61 62 assert((sid != NULL) && (acct != NULL)); 63 64 bzero(acct, sizeof (lsa_account_t)); 65 (void) strlcpy(acct->a_sid, sid, SMB_SID_STRSZ); 66 67 if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 68 return (-1); 69 70 buf = smb_dr_encode_common(opcode, acct, lsa_account_xdr, &len); 71 if (buf == NULL) { 72 (void) close(fd); 73 return (-1); 74 } 75 76 smb_dr_clnt_setup(&arg, buf, len); 77 78 if ((rc = smb_dr_clnt_call(fd, &arg)) == 0) { 79 buf = arg.rbuf + SMB_DR_DATA_OFFSET; 80 len = arg.rsize - SMB_DR_DATA_OFFSET; 81 82 rc = smb_dr_decode_common(buf, len, lsa_account_xdr, acct); 83 } 84 85 smb_dr_clnt_cleanup(&arg); 86 (void) close(fd); 87 return (rc); 88 } 89 90 /* 91 * Given a name, make a door call to get the associated SID. 92 * 93 * Returns 0 if the door call is successful, otherwise -1. 94 * 95 * If 0 is returned, the lookup result will be available in a_status. 96 * NT_STATUS_SUCCESS The name was mapped to a SID. 97 * NT_STATUS_NONE_MAPPED The name could not be mapped to a SID. 98 */ 99 int 100 smb_lookup_name(const char *name, sid_type_t sidtype, lsa_account_t *acct) 101 { 102 char tmp[MAXNAMELEN]; 103 door_arg_t arg; 104 char *buf; 105 char *dp = NULL; 106 char *np = NULL; 107 size_t len; 108 int opcode = SMB_DR_LOOKUP_NAME; 109 int fd; 110 int rc; 111 112 assert((name != NULL) && (acct != NULL)); 113 114 (void) strlcpy(tmp, name, MAXNAMELEN); 115 smb_name_parse(tmp, &np, &dp); 116 117 bzero(acct, sizeof (lsa_account_t)); 118 acct->a_sidtype = sidtype; 119 120 if (dp != NULL && np != NULL) { 121 (void) strlcpy(acct->a_domain, dp, MAXNAMELEN); 122 (void) strlcpy(acct->a_name, np, MAXNAMELEN); 123 } else { 124 (void) strlcpy(acct->a_name, name, MAXNAMELEN); 125 } 126 127 if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 128 return (-1); 129 130 buf = smb_dr_encode_common(opcode, acct, lsa_account_xdr, &len); 131 if (buf == NULL) { 132 (void) close(fd); 133 return (-1); 134 } 135 136 smb_dr_clnt_setup(&arg, buf, len); 137 138 if ((rc = smb_dr_clnt_call(fd, &arg)) == 0) { 139 buf = arg.rbuf + SMB_DR_DATA_OFFSET; 140 len = arg.rsize - SMB_DR_DATA_OFFSET; 141 142 rc = smb_dr_decode_common(buf, len, lsa_account_xdr, acct); 143 } 144 145 smb_dr_clnt_cleanup(&arg); 146 (void) close(fd); 147 return (rc); 148 } 149 150 uint32_t 151 smb_join(smb_joininfo_t *jdi) 152 { 153 door_arg_t arg; 154 char *buf; 155 size_t len; 156 int opcode = SMB_DR_JOIN; 157 uint32_t status; 158 int fd, rc; 159 160 if (jdi == NULL) 161 return (NT_STATUS_INVALID_PARAMETER); 162 163 if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 164 return (NT_STATUS_INTERNAL_ERROR); 165 166 buf = smb_dr_encode_common(opcode, jdi, xdr_smb_dr_joininfo_t, &len); 167 if (buf == NULL) { 168 (void) close(fd); 169 return (NT_STATUS_INTERNAL_ERROR); 170 } 171 172 smb_dr_clnt_setup(&arg, buf, len); 173 174 if (smb_dr_clnt_call(fd, &arg) == 0) { 175 buf = arg.rbuf + SMB_DR_DATA_OFFSET; 176 len = arg.rsize - SMB_DR_DATA_OFFSET; 177 rc = smb_dr_decode_common(buf, len, xdr_uint32_t, &status); 178 if (rc != 0) 179 status = NT_STATUS_INTERNAL_ERROR; 180 } else { 181 status = NT_STATUS_INTERNAL_ERROR; 182 } 183 184 smb_dr_clnt_cleanup(&arg); 185 (void) close(fd); 186 return (status); 187 } 188 189 /* 190 * Gets information about the Domain Controller in the joined resource domain. 191 * 192 * Returns: NT_STATUS_SUCCESS if the successful in getting 193 * domain information. 194 */ 195 uint32_t 196 smb_get_dcinfo(char *namebuf, uint32_t namebuflen, smb_inaddr_t *ipaddr) 197 { 198 door_arg_t arg; 199 char *buf; 200 size_t len; 201 int opcode = SMB_DR_GET_DCINFO; 202 int fd; 203 char *srvname = NULL; 204 struct hostent *h; 205 int error_num; 206 207 assert((namebuf != NULL) && (namebuflen != 0)); 208 *namebuf = '\0'; 209 210 if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 211 return (NT_STATUS_INTERNAL_ERROR); 212 213 if ((buf = smb_dr_set_opcode(opcode, &len)) == NULL) { 214 (void) close(fd); 215 return (NT_STATUS_INTERNAL_ERROR); 216 } 217 218 smb_dr_clnt_setup(&arg, buf, len); 219 220 if (smb_dr_clnt_call(fd, &arg) == 0) { 221 buf = arg.rbuf + SMB_DR_DATA_OFFSET; 222 len = arg.rsize - SMB_DR_DATA_OFFSET; 223 srvname = smb_dr_decode_string(buf, len); 224 } 225 226 smb_dr_clnt_cleanup(&arg); 227 (void) close(fd); 228 229 if (srvname) { 230 (void) strlcpy(namebuf, srvname, namebuflen); 231 if ((h = smb_gethostbyname(srvname, &error_num)) == NULL) { 232 bzero(ipaddr, sizeof (smb_inaddr_t)); 233 } else { 234 (void) memcpy(ipaddr, h->h_addr, h->h_length); 235 ipaddr->a_family = h->h_addrtype; 236 freehostent(h); 237 } 238 xdr_free(xdr_string, (char *)&srvname); 239 } 240 return (NT_STATUS_SUCCESS); 241 } 242 243 bool_t 244 xdr_smb_dr_joininfo_t(XDR *xdrs, smb_joininfo_t *objp) 245 { 246 if (!xdr_vector(xdrs, (char *)objp->domain_name, MAXHOSTNAMELEN, 247 sizeof (char), (xdrproc_t)xdr_char)) 248 return (FALSE); 249 250 if (!xdr_vector(xdrs, (char *)objp->domain_username, 251 SMB_USERNAME_MAXLEN + 1, sizeof (char), (xdrproc_t)xdr_char)) 252 return (FALSE); 253 254 if (!xdr_vector(xdrs, (char *)objp->domain_passwd, 255 SMB_PASSWD_MAXLEN + 1, sizeof (char), (xdrproc_t)xdr_char)) 256 return (FALSE); 257 258 if (!xdr_uint32_t(xdrs, &objp->mode)) 259 return (FALSE); 260 261 return (TRUE); 262 } 263 264 /* 265 * Parameters: 266 * fqdn (input) - fully-qualified domain name 267 * srvbuf (output) - fully-qualified hostname of the AD server found 268 * by this function. 269 * srvbuflen (input) - length of the 'buf' 270 * 271 * Return: 272 * B_TRUE if an AD server is found. Otherwise, returns B_FALSE; 273 * 274 * The buffer passed in should be big enough to hold a fully-qualified 275 * hostname (MAXHOSTNAMELEN); otherwise, a truncated string will be 276 * returned. On error, an empty string will be returned. 277 */ 278 boolean_t 279 smb_find_ads_server(char *fqdn, char *srvbuf, int srvbuflen) 280 { 281 door_arg_t arg; 282 char *buf; 283 size_t len; 284 int opcode = SMB_DR_ADS_FIND_HOST; 285 char *server = NULL; 286 int fd; 287 boolean_t found = B_FALSE; 288 289 if (!srvbuf) 290 return (B_FALSE); 291 292 *srvbuf = '\0'; 293 294 if (!fqdn) 295 return (B_FALSE); 296 297 if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) 298 return (B_FALSE); 299 300 if ((buf = smb_dr_encode_string(opcode, fqdn, &len)) == 0) { 301 (void) close(fd); 302 return (B_FALSE); 303 } 304 305 smb_dr_clnt_setup(&arg, buf, len); 306 307 if (smb_dr_clnt_call(fd, &arg) == 0) { 308 buf = arg.rbuf + SMB_DR_DATA_OFFSET; 309 len = arg.rsize - SMB_DR_DATA_OFFSET; 310 if ((server = smb_dr_decode_string(buf, len)) != NULL) { 311 if (*server != '\0') { 312 (void) strlcpy(srvbuf, server, srvbuflen); 313 found = B_TRUE; 314 } 315 xdr_free(xdr_string, (char *)&server); 316 } 317 } 318 319 smb_dr_clnt_cleanup(&arg); 320 (void) close(fd); 321 322 return (found); 323 } 324