Home | History | Annotate | Download | only in common
      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