xref: /titanic_53/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c (revision b3700b074e637f8c6991b70754c88a2cfffb246b)
189dc44ceSjose borrego /*
289dc44ceSjose borrego  * CDDL HEADER START
389dc44ceSjose borrego  *
489dc44ceSjose borrego  * The contents of this file are subject to the terms of the
589dc44ceSjose borrego  * Common Development and Distribution License (the "License").
689dc44ceSjose borrego  * You may not use this file except in compliance with the License.
789dc44ceSjose borrego  *
889dc44ceSjose borrego  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
989dc44ceSjose borrego  * or http://www.opensolaris.org/os/licensing.
1089dc44ceSjose borrego  * See the License for the specific language governing permissions
1189dc44ceSjose borrego  * and limitations under the License.
1289dc44ceSjose borrego  *
1389dc44ceSjose borrego  * When distributing Covered Code, include this CDDL HEADER in each
1489dc44ceSjose borrego  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1589dc44ceSjose borrego  * If applicable, add the following below this CDDL HEADER, with the
1689dc44ceSjose borrego  * fields enclosed by brackets "[]" replaced with your own identifying
1789dc44ceSjose borrego  * information: Portions Copyright [yyyy] [name of copyright owner]
1889dc44ceSjose borrego  *
1989dc44ceSjose borrego  * CDDL HEADER END
2089dc44ceSjose borrego  */
21148c5f43SAlan Wright 
2289dc44ceSjose borrego /*
23148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*b3700b07SGordon Ross  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
2589dc44ceSjose borrego  */
2689dc44ceSjose borrego 
2789dc44ceSjose borrego /*
2889dc44ceSjose borrego  * Server Service (srvsvc) client side RPC library interface. The
2989dc44ceSjose borrego  * srvsvc interface allows a client to query a server for information
3089dc44ceSjose borrego  * on shares, sessions, connections and files on the server. Some
3189dc44ceSjose borrego  * functions are available via anonymous IPC while others require
3289dc44ceSjose borrego  * administrator privilege. Also, some functions return NT status
3389dc44ceSjose borrego  * values while others return Win32 errors codes.
3489dc44ceSjose borrego  */
3589dc44ceSjose borrego 
3689dc44ceSjose borrego #include <sys/errno.h>
3789dc44ceSjose borrego #include <stdio.h>
3889dc44ceSjose borrego #include <time.h>
3989dc44ceSjose borrego #include <strings.h>
4089dc44ceSjose borrego 
4189dc44ceSjose borrego #include <smbsrv/libsmb.h>
4289dc44ceSjose borrego #include <smbsrv/libmlsvc.h>
4389dc44ceSjose borrego #include <smbsrv/smbinfo.h>
4489dc44ceSjose borrego #include <smbsrv/ndl/srvsvc.ndl>
4589dc44ceSjose borrego 
4689dc44ceSjose borrego /*
4789dc44ceSjose borrego  * Information level for NetShareGetInfo.
4889dc44ceSjose borrego  */
4989dc44ceSjose borrego DWORD srvsvc_info_level = 1;
5089dc44ceSjose borrego 
5189dc44ceSjose borrego /*
5289dc44ceSjose borrego  * Bind to the the SRVSVC.
5389dc44ceSjose borrego  *
5489dc44ceSjose borrego  * If username argument is NULL, an anonymous connection will be established.
5589dc44ceSjose borrego  * Otherwise, an authenticated connection will be established.
5689dc44ceSjose borrego  */
5789dc44ceSjose borrego static int
srvsvc_open(char * server,char * domain,char * username,mlsvc_handle_t * handle)5889dc44ceSjose borrego srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle)
5989dc44ceSjose borrego {
60a0aa776eSAlan Wright 	smb_domainex_t di;
6189dc44ceSjose borrego 
6289dc44ceSjose borrego 	if (server == NULL || domain == NULL) {
6389dc44ceSjose borrego 		if (!smb_domain_getinfo(&di))
6489dc44ceSjose borrego 			return (-1);
6589dc44ceSjose borrego 
66*b3700b07SGordon Ross 		server = di.d_dci.dc_name;
67a0aa776eSAlan Wright 		domain = di.d_primary.di_nbname;
6889dc44ceSjose borrego 	}
6989dc44ceSjose borrego 
7089dc44ceSjose borrego 	if (username == NULL)
7189dc44ceSjose borrego 		username = MLSVC_ANON_USER;
7289dc44ceSjose borrego 
73*b3700b07SGordon Ross 	if (ndr_rpc_bind(handle, server, domain, username, "SRVSVC") != 0)
7489dc44ceSjose borrego 		return (-1);
7589dc44ceSjose borrego 
7689dc44ceSjose borrego 	return (0);
7789dc44ceSjose borrego }
7889dc44ceSjose borrego 
7989dc44ceSjose borrego /*
8089dc44ceSjose borrego  * Unbind the SRVSVC connection.
8189dc44ceSjose borrego  */
8289dc44ceSjose borrego static void
srvsvc_close(mlsvc_handle_t * handle)8389dc44ceSjose borrego srvsvc_close(mlsvc_handle_t *handle)
8489dc44ceSjose borrego {
8589dc44ceSjose borrego 	ndr_rpc_unbind(handle);
8689dc44ceSjose borrego }
8789dc44ceSjose borrego 
8889dc44ceSjose borrego /*
8989dc44ceSjose borrego  * This is a client side routine for NetShareGetInfo.
9089dc44ceSjose borrego  * Levels 0 and 1 work with an anonymous connection but
9189dc44ceSjose borrego  * level 2 requires administrator access.
9289dc44ceSjose borrego  */
9389dc44ceSjose borrego int
srvsvc_net_share_get_info(char * server,char * domain,char * netname)9489dc44ceSjose borrego srvsvc_net_share_get_info(char *server, char *domain, char *netname)
9589dc44ceSjose borrego {
9689dc44ceSjose borrego 	struct mlsm_NetShareGetInfo arg;
9789dc44ceSjose borrego 	mlsvc_handle_t handle;
9889dc44ceSjose borrego 	int rc;
9989dc44ceSjose borrego 	int opnum;
100eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	struct mslm_NetShareInfo_0 *info0;
101eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	struct mslm_NetShareInfo_1 *info1;
102eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	struct mslm_NetShareInfo_2 *info2;
10389dc44ceSjose borrego 	int len;
104a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
10589dc44ceSjose borrego 
10689dc44ceSjose borrego 	if (netname == NULL)
10789dc44ceSjose borrego 		return (-1);
10889dc44ceSjose borrego 
10989dc44ceSjose borrego 	if (srvsvc_info_level == 2)
110a0aa776eSAlan Wright 		smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
11189dc44ceSjose borrego 
11289dc44ceSjose borrego 	if (srvsvc_open(server, domain, user, &handle) != 0)
11389dc44ceSjose borrego 		return (-1);
11489dc44ceSjose borrego 
11589dc44ceSjose borrego 	opnum = SRVSVC_OPNUM_NetShareGetInfo;
11689dc44ceSjose borrego 	bzero(&arg, sizeof (struct mlsm_NetShareGetInfo));
11789dc44ceSjose borrego 
11889dc44ceSjose borrego 	len = strlen(server) + 4;
11989dc44ceSjose borrego 	arg.servername = ndr_rpc_malloc(&handle, len);
12089dc44ceSjose borrego 	if (arg.servername == NULL) {
12189dc44ceSjose borrego 		srvsvc_close(&handle);
12289dc44ceSjose borrego 		return (-1);
12389dc44ceSjose borrego 	}
12489dc44ceSjose borrego 
12589dc44ceSjose borrego 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
12689dc44ceSjose borrego 	arg.netname = (LPTSTR)netname;
12789dc44ceSjose borrego 	arg.level = srvsvc_info_level; /* share information level */
12889dc44ceSjose borrego 
12989dc44ceSjose borrego 	rc = ndr_rpc_call(&handle, opnum, &arg);
13089dc44ceSjose borrego 	if ((rc != 0) || (arg.status != 0)) {
13189dc44ceSjose borrego 		srvsvc_close(&handle);
13289dc44ceSjose borrego 		return (-1);
13389dc44ceSjose borrego 	}
13489dc44ceSjose borrego 
13589dc44ceSjose borrego 	switch (arg.result.switch_value) {
13689dc44ceSjose borrego 	case 0:
13789dc44ceSjose borrego 		info0 = arg.result.ru.info0;
13889dc44ceSjose borrego 		smb_tracef("srvsvc shi0_netname=%s", info0->shi0_netname);
13989dc44ceSjose borrego 		break;
14089dc44ceSjose borrego 
14189dc44ceSjose borrego 	case 1:
14289dc44ceSjose borrego 		info1 = arg.result.ru.info1;
14389dc44ceSjose borrego 		smb_tracef("srvsvc shi1_netname=%s", info1->shi1_netname);
14489dc44ceSjose borrego 		smb_tracef("srvsvc shi1_type=%u", info1->shi1_type);
14589dc44ceSjose borrego 
14689dc44ceSjose borrego 		if (info1->shi1_comment)
14789dc44ceSjose borrego 			smb_tracef("srvsvc shi1_comment=%s",
14889dc44ceSjose borrego 			    info1->shi1_comment);
14989dc44ceSjose borrego 		break;
15089dc44ceSjose borrego 
15189dc44ceSjose borrego 	case 2:
15289dc44ceSjose borrego 		info2 = arg.result.ru.info2;
15389dc44ceSjose borrego 		smb_tracef("srvsvc shi2_netname=%s", info2->shi2_netname);
15489dc44ceSjose borrego 		smb_tracef("srvsvc shi2_type=%u", info2->shi2_type);
15589dc44ceSjose borrego 
15689dc44ceSjose borrego 		if (info2->shi2_comment)
15789dc44ceSjose borrego 			smb_tracef("srvsvc shi2_comment=%s",
15889dc44ceSjose borrego 			    info2->shi2_comment);
15989dc44ceSjose borrego 
16089dc44ceSjose borrego 		smb_tracef("srvsvc shi2_perms=%d", info2->shi2_permissions);
16189dc44ceSjose borrego 		smb_tracef("srvsvc shi2_max_use=%d", info2->shi2_max_uses);
16289dc44ceSjose borrego 		smb_tracef("srvsvc shi2_cur_use=%d", info2->shi2_current_uses);
16389dc44ceSjose borrego 
16489dc44ceSjose borrego 		if (info2->shi2_path)
16589dc44ceSjose borrego 			smb_tracef("srvsvc shi2_path=%s", info2->shi2_path);
16689dc44ceSjose borrego 
16789dc44ceSjose borrego 		if (info2->shi2_passwd)
16889dc44ceSjose borrego 			smb_tracef("srvsvc shi2_passwd=%s", info2->shi2_passwd);
16989dc44ceSjose borrego 		break;
17089dc44ceSjose borrego 
17189dc44ceSjose borrego 	default:
17289dc44ceSjose borrego 		smb_tracef("srvsvc: unknown level");
17389dc44ceSjose borrego 		break;
17489dc44ceSjose borrego 	}
17589dc44ceSjose borrego 
17689dc44ceSjose borrego 	srvsvc_close(&handle);
17789dc44ceSjose borrego 	return (0);
17889dc44ceSjose borrego }
17989dc44ceSjose borrego 
18089dc44ceSjose borrego /*
18189dc44ceSjose borrego  * This is a client side routine for NetSessionEnum.
18289dc44ceSjose borrego  * NetSessionEnum requires administrator rights.
18389dc44ceSjose borrego  */
18489dc44ceSjose borrego int
srvsvc_net_session_enum(char * server,char * domain,char * netname)18589dc44ceSjose borrego srvsvc_net_session_enum(char *server, char *domain, char *netname)
18689dc44ceSjose borrego {
18789dc44ceSjose borrego 	struct mslm_NetSessionEnum arg;
18889dc44ceSjose borrego 	mlsvc_handle_t handle;
18989dc44ceSjose borrego 	int rc;
19089dc44ceSjose borrego 	int opnum;
19189dc44ceSjose borrego 	struct mslm_infonres infonres;
19289dc44ceSjose borrego 	struct mslm_SESSION_INFO_1 *nsi1;
19389dc44ceSjose borrego 	int len;
194a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
19589dc44ceSjose borrego 
19689dc44ceSjose borrego 	if (netname == NULL)
19789dc44ceSjose borrego 		return (-1);
19889dc44ceSjose borrego 
199a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
200a0aa776eSAlan Wright 
20189dc44ceSjose borrego 	rc = srvsvc_open(server, domain, user, &handle);
20289dc44ceSjose borrego 	if (rc != 0)
20389dc44ceSjose borrego 		return (-1);
20489dc44ceSjose borrego 
20589dc44ceSjose borrego 	opnum = SRVSVC_OPNUM_NetSessionEnum;
20689dc44ceSjose borrego 	bzero(&arg, sizeof (struct mslm_NetSessionEnum));
20789dc44ceSjose borrego 
20889dc44ceSjose borrego 	len = strlen(server) + 4;
20989dc44ceSjose borrego 	arg.servername = ndr_rpc_malloc(&handle, len);
21089dc44ceSjose borrego 	if (arg.servername == NULL) {
21189dc44ceSjose borrego 		srvsvc_close(&handle);
21289dc44ceSjose borrego 		return (-1);
21389dc44ceSjose borrego 	}
21489dc44ceSjose borrego 
21589dc44ceSjose borrego 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
21689dc44ceSjose borrego 	infonres.entriesread = 0;
21789dc44ceSjose borrego 	infonres.entries = 0;
21889dc44ceSjose borrego 	arg.level = 1;
21989dc44ceSjose borrego 	arg.result.level = 1;
22089dc44ceSjose borrego 	arg.result.bufptr.p = &infonres;
22189dc44ceSjose borrego 	arg.resume_handle = 0;
22289dc44ceSjose borrego 	arg.pref_max_len = 0xFFFFFFFF;
22389dc44ceSjose borrego 
22489dc44ceSjose borrego 	rc = ndr_rpc_call(&handle, opnum, &arg);
22589dc44ceSjose borrego 	if ((rc != 0) || (arg.status != 0)) {
22689dc44ceSjose borrego 		srvsvc_close(&handle);
22789dc44ceSjose borrego 		return (-1);
22889dc44ceSjose borrego 	}
22989dc44ceSjose borrego 
23089dc44ceSjose borrego 	/* Only the first session info is dereferenced. */
23189dc44ceSjose borrego 	nsi1 = ((struct mslm_infonres *)arg.result.bufptr.p)->entries;
23289dc44ceSjose borrego 
23389dc44ceSjose borrego 	smb_tracef("srvsvc switch_value=%d", arg.level);
23489dc44ceSjose borrego 	smb_tracef("srvsvc sesi1_cname=%s", nsi1->sesi1_cname);
23589dc44ceSjose borrego 	smb_tracef("srvsvc sesi1_uname=%s", nsi1->sesi1_uname);
23689dc44ceSjose borrego 	smb_tracef("srvsvc sesi1_nopens=%u", nsi1->sesi1_nopens);
23789dc44ceSjose borrego 	smb_tracef("srvsvc sesi1_time=%u", nsi1->sesi1_time);
23889dc44ceSjose borrego 	smb_tracef("srvsvc sesi1_itime=%u", nsi1->sesi1_itime);
23989dc44ceSjose borrego 	smb_tracef("srvsvc sesi1_uflags=%u", nsi1->sesi1_uflags);
24089dc44ceSjose borrego 
24189dc44ceSjose borrego 	srvsvc_close(&handle);
24289dc44ceSjose borrego 	return (0);
24389dc44ceSjose borrego }
24489dc44ceSjose borrego 
24589dc44ceSjose borrego /*
24689dc44ceSjose borrego  * This is a client side routine for NetConnectEnum.
24789dc44ceSjose borrego  * NetConnectEnum requires administrator rights.
24889dc44ceSjose borrego  * Level 0 and level 1 requests are supported.
24989dc44ceSjose borrego  */
25089dc44ceSjose borrego int
srvsvc_net_connect_enum(char * server,char * domain,char * netname,int level)25189dc44ceSjose borrego srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level)
25289dc44ceSjose borrego {
25389dc44ceSjose borrego 	struct mslm_NetConnectEnum arg;
25489dc44ceSjose borrego 	mlsvc_handle_t handle;
25589dc44ceSjose borrego 	int rc;
25689dc44ceSjose borrego 	int opnum;
25789dc44ceSjose borrego 	struct mslm_NetConnectInfo1 info1;
25889dc44ceSjose borrego 	struct mslm_NetConnectInfo0 info0;
25989dc44ceSjose borrego 	struct mslm_NetConnectInfoBuf1 *cib1;
26089dc44ceSjose borrego 	int len;
261a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
26289dc44ceSjose borrego 
26389dc44ceSjose borrego 	if (netname == NULL)
26489dc44ceSjose borrego 		return (-1);
26589dc44ceSjose borrego 
266a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
267a0aa776eSAlan Wright 
26889dc44ceSjose borrego 	rc = srvsvc_open(server, domain, user, &handle);
26989dc44ceSjose borrego 	if (rc != 0)
27089dc44ceSjose borrego 		return (-1);
27189dc44ceSjose borrego 
27289dc44ceSjose borrego 	opnum = SRVSVC_OPNUM_NetConnectEnum;
27389dc44ceSjose borrego 	bzero(&arg, sizeof (struct mslm_NetConnectEnum));
27489dc44ceSjose borrego 
27589dc44ceSjose borrego 	len = strlen(server) + 4;
27689dc44ceSjose borrego 	arg.servername = ndr_rpc_malloc(&handle, len);
27789dc44ceSjose borrego 	if (arg.servername == NULL) {
27889dc44ceSjose borrego 		srvsvc_close(&handle);
27989dc44ceSjose borrego 		return (-1);
28089dc44ceSjose borrego 	}
28189dc44ceSjose borrego 
28289dc44ceSjose borrego 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
28389dc44ceSjose borrego 	arg.qualifier = (LPTSTR)netname;
28489dc44ceSjose borrego 
28589dc44ceSjose borrego 	switch (level) {
28689dc44ceSjose borrego 	case 0:
28789dc44ceSjose borrego 		arg.info.level = 0;
28889dc44ceSjose borrego 		arg.info.switch_value = 0;
28989dc44ceSjose borrego 		arg.info.ru.info0 = &info0;
29089dc44ceSjose borrego 		info0.entries_read = 0;
29189dc44ceSjose borrego 		info0.ci0 = 0;
29289dc44ceSjose borrego 		break;
29389dc44ceSjose borrego 	case 1:
29489dc44ceSjose borrego 		arg.info.level = 1;
29589dc44ceSjose borrego 		arg.info.switch_value = 1;
29689dc44ceSjose borrego 		arg.info.ru.info1 = &info1;
29789dc44ceSjose borrego 		info1.entries_read = 0;
29889dc44ceSjose borrego 		info1.ci1 = 0;
29989dc44ceSjose borrego 		break;
30089dc44ceSjose borrego 	default:
30189dc44ceSjose borrego 		srvsvc_close(&handle);
30289dc44ceSjose borrego 		return (-1);
30389dc44ceSjose borrego 	}
30489dc44ceSjose borrego 
30589dc44ceSjose borrego 	arg.resume_handle = 0;
30689dc44ceSjose borrego 	arg.pref_max_len = 0xFFFFFFFF;
30789dc44ceSjose borrego 
30889dc44ceSjose borrego 	rc = ndr_rpc_call(&handle, opnum, &arg);
30989dc44ceSjose borrego 	if ((rc != 0) || (arg.status != 0)) {
31089dc44ceSjose borrego 		srvsvc_close(&handle);
31189dc44ceSjose borrego 		return (-1);
31289dc44ceSjose borrego 	}
31389dc44ceSjose borrego 
31489dc44ceSjose borrego 	smb_tracef("srvsvc switch_value=%d", arg.info.switch_value);
31589dc44ceSjose borrego 
31689dc44ceSjose borrego 	switch (level) {
31789dc44ceSjose borrego 	case 0:
31889dc44ceSjose borrego 		if (arg.info.ru.info0 && arg.info.ru.info0->ci0) {
31989dc44ceSjose borrego 			smb_tracef("srvsvc coni0_id=%x",
32089dc44ceSjose borrego 			    arg.info.ru.info0->ci0->coni0_id);
32189dc44ceSjose borrego 		}
32289dc44ceSjose borrego 		break;
32389dc44ceSjose borrego 	case 1:
32489dc44ceSjose borrego 		if (arg.info.ru.info1 && arg.info.ru.info1->ci1) {
32589dc44ceSjose borrego 			cib1 = arg.info.ru.info1->ci1;
32689dc44ceSjose borrego 
32789dc44ceSjose borrego 			smb_tracef("srvsvc coni_uname=%s",
32889dc44ceSjose borrego 			    cib1->coni1_username ?
32989dc44ceSjose borrego 			    (char *)cib1->coni1_username : "(null)");
33089dc44ceSjose borrego 			smb_tracef("srvsvc coni1_netname=%s",
33189dc44ceSjose borrego 			    cib1->coni1_netname ?
33289dc44ceSjose borrego 			    (char *)cib1->coni1_netname : "(null)");
33389dc44ceSjose borrego 			smb_tracef("srvsvc coni1_nopens=%u",
33489dc44ceSjose borrego 			    cib1->coni1_num_opens);
33589dc44ceSjose borrego 			smb_tracef("srvsvc coni1_time=%u", cib1->coni1_time);
33689dc44ceSjose borrego 			smb_tracef("srvsvc coni1_num_users=%u",
33789dc44ceSjose borrego 			    cib1->coni1_num_users);
33889dc44ceSjose borrego 		}
33989dc44ceSjose borrego 		break;
34089dc44ceSjose borrego 
34189dc44ceSjose borrego 	default:
34289dc44ceSjose borrego 		smb_tracef("srvsvc: unknown level");
34389dc44ceSjose borrego 		break;
34489dc44ceSjose borrego 	}
34589dc44ceSjose borrego 
34689dc44ceSjose borrego 	srvsvc_close(&handle);
34789dc44ceSjose borrego 	return (0);
34889dc44ceSjose borrego }
34989dc44ceSjose borrego 
350a0aa776eSAlan Wright /*
351a0aa776eSAlan Wright  * Windows 95+ and Windows NT4.0 both report the version as 4.0.
352a0aa776eSAlan Wright  * Windows 2000+ reports the version as 5.x.
353a0aa776eSAlan Wright  */
3541fcced4cSJordan Brown int
srvsvc_net_server_getinfo(char * server,char * domain,srvsvc_server_info_t * svinfo)3551fcced4cSJordan Brown srvsvc_net_server_getinfo(char *server, char *domain,
3561fcced4cSJordan Brown     srvsvc_server_info_t *svinfo)
3571fcced4cSJordan Brown {
3581fcced4cSJordan Brown 	mlsvc_handle_t handle;
3591fcced4cSJordan Brown 	struct mslm_NetServerGetInfo arg;
3601fcced4cSJordan Brown 	struct mslm_SERVER_INFO_101 *sv101;
3611fcced4cSJordan Brown 	int len, opnum, rc;
362a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
363a0aa776eSAlan Wright 
364a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
3651fcced4cSJordan Brown 
3661fcced4cSJordan Brown 	if (srvsvc_open(server, domain, user, &handle) != 0)
3671fcced4cSJordan Brown 		return (-1);
3681fcced4cSJordan Brown 
3691fcced4cSJordan Brown 	opnum = SRVSVC_OPNUM_NetServerGetInfo;
3701fcced4cSJordan Brown 	bzero(&arg, sizeof (arg));
3711fcced4cSJordan Brown 
3721fcced4cSJordan Brown 	len = strlen(server) + 4;
3731fcced4cSJordan Brown 	arg.servername = ndr_rpc_malloc(&handle, len);
3741fcced4cSJordan Brown 	if (arg.servername == NULL)
3751fcced4cSJordan Brown 		return (-1);
3761fcced4cSJordan Brown 
3771fcced4cSJordan Brown 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
3781fcced4cSJordan Brown 	arg.level = 101;
3791fcced4cSJordan Brown 
3801fcced4cSJordan Brown 	rc = ndr_rpc_call(&handle, opnum, &arg);
3811fcced4cSJordan Brown 	if ((rc != 0) || (arg.status != 0)) {
3821fcced4cSJordan Brown 		srvsvc_close(&handle);
3831fcced4cSJordan Brown 		return (-1);
3841fcced4cSJordan Brown 	}
3851fcced4cSJordan Brown 
3861fcced4cSJordan Brown 	sv101 = arg.result.bufptr.bufptr101;
3871fcced4cSJordan Brown 
3881fcced4cSJordan Brown 	bzero(svinfo, sizeof (srvsvc_server_info_t));
3891fcced4cSJordan Brown 	svinfo->sv_platform_id = sv101->sv101_platform_id;
3901fcced4cSJordan Brown 	svinfo->sv_version_major = sv101->sv101_version_major;
3911fcced4cSJordan Brown 	svinfo->sv_version_minor = sv101->sv101_version_minor;
3921fcced4cSJordan Brown 	svinfo->sv_type = sv101->sv101_type;
3931fcced4cSJordan Brown 	if (sv101->sv101_name)
3941fcced4cSJordan Brown 		svinfo->sv_name = strdup((char *)sv101->sv101_name);
3951fcced4cSJordan Brown 	if (sv101->sv101_comment)
3961fcced4cSJordan Brown 		svinfo->sv_comment = strdup((char *)sv101->sv101_comment);
3971fcced4cSJordan Brown 
398a0aa776eSAlan Wright 	if (svinfo->sv_type & SV_TYPE_WFW)
399a0aa776eSAlan Wright 		svinfo->sv_os = NATIVE_OS_WIN95;
400a0aa776eSAlan Wright 	if (svinfo->sv_type & SV_TYPE_WINDOWS)
401a0aa776eSAlan Wright 		svinfo->sv_os = NATIVE_OS_WIN95;
402a0aa776eSAlan Wright 	if ((svinfo->sv_type & SV_TYPE_NT) ||
403a0aa776eSAlan Wright 	    (svinfo->sv_type & SV_TYPE_SERVER_NT))
404a0aa776eSAlan Wright 		svinfo->sv_os = NATIVE_OS_WINNT;
405a0aa776eSAlan Wright 	if (svinfo->sv_version_major > 4)
406a0aa776eSAlan Wright 		svinfo->sv_os = NATIVE_OS_WIN2000;
407a0aa776eSAlan Wright 
4081fcced4cSJordan Brown 	srvsvc_close(&handle);
4091fcced4cSJordan Brown 	return (0);
4101fcced4cSJordan Brown }
4111fcced4cSJordan Brown 
41289dc44ceSjose borrego /*
41389dc44ceSjose borrego  * Synchronize the local system clock with the domain controller.
41489dc44ceSjose borrego  */
41589dc44ceSjose borrego void
srvsvc_timesync(void)41689dc44ceSjose borrego srvsvc_timesync(void)
41789dc44ceSjose borrego {
418a0aa776eSAlan Wright 	smb_domainex_t di;
41989dc44ceSjose borrego 	struct timeval tv;
42089dc44ceSjose borrego 	struct tm tm;
42189dc44ceSjose borrego 	time_t tsecs;
42289dc44ceSjose borrego 
42389dc44ceSjose borrego 	if (!smb_domain_getinfo(&di))
42489dc44ceSjose borrego 		return;
42589dc44ceSjose borrego 
426*b3700b07SGordon Ross 	if (srvsvc_net_remote_tod(di.d_dci.dc_name, di.d_primary.di_nbname,
427*b3700b07SGordon Ross 	    &tv, &tm) != 0)
42889dc44ceSjose borrego 		return;
42989dc44ceSjose borrego 
43089dc44ceSjose borrego 	if (settimeofday(&tv, 0))
43189dc44ceSjose borrego 		smb_tracef("unable to set system time");
43289dc44ceSjose borrego 
43389dc44ceSjose borrego 	tsecs = time(0);
43489dc44ceSjose borrego 	(void) localtime_r(&tsecs, &tm);
43589dc44ceSjose borrego 	smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec));
43689dc44ceSjose borrego }
43789dc44ceSjose borrego 
43889dc44ceSjose borrego /*
43989dc44ceSjose borrego  * NetRemoteTOD to get the current GMT time from a Windows NT server.
44089dc44ceSjose borrego  */
44189dc44ceSjose borrego int
srvsvc_gettime(unsigned long * t)44289dc44ceSjose borrego srvsvc_gettime(unsigned long *t)
44389dc44ceSjose borrego {
444a0aa776eSAlan Wright 	smb_domainex_t di;
44589dc44ceSjose borrego 	struct timeval tv;
44689dc44ceSjose borrego 	struct tm tm;
44789dc44ceSjose borrego 
44889dc44ceSjose borrego 	if (!smb_domain_getinfo(&di))
44989dc44ceSjose borrego 		return (-1);
45089dc44ceSjose borrego 
451*b3700b07SGordon Ross 	if (srvsvc_net_remote_tod(di.d_dci.dc_name, di.d_primary.di_nbname,
452*b3700b07SGordon Ross 	    &tv, &tm) != 0)
45389dc44ceSjose borrego 		return (-1);
45489dc44ceSjose borrego 
45589dc44ceSjose borrego 	*t = tv.tv_sec;
45689dc44ceSjose borrego 	return (0);
45789dc44ceSjose borrego }
45889dc44ceSjose borrego 
45989dc44ceSjose borrego /*
46089dc44ceSjose borrego  * This is a client side routine for NetRemoteTOD, which gets the time
46189dc44ceSjose borrego  * and date from a remote system. The time information is returned in
46289dc44ceSjose borrego  * the timeval and tm.
46389dc44ceSjose borrego  *
46489dc44ceSjose borrego  * typedef struct _TIME_OF_DAY_INFO {
46589dc44ceSjose borrego  *	DWORD tod_elapsedt;  // seconds since 00:00:00 January 1 1970 GMT
46689dc44ceSjose borrego  *	DWORD tod_msecs;     // arbitrary milliseconds (since reset)
46789dc44ceSjose borrego  *	DWORD tod_hours;     // current hour [0-23]
46889dc44ceSjose borrego  *	DWORD tod_mins;      // current minute [0-59]
46989dc44ceSjose borrego  *	DWORD tod_secs;      // current second [0-59]
47089dc44ceSjose borrego  *	DWORD tod_hunds;     // current hundredth (0.01) second [0-99]
47189dc44ceSjose borrego  *	LONG tod_timezone;   // time zone of the server
47289dc44ceSjose borrego  *	DWORD tod_tinterval; // clock tick time interval
47389dc44ceSjose borrego  *	DWORD tod_day;       // day of the month [1-31]
47489dc44ceSjose borrego  *	DWORD tod_month;     // month of the year [1-12]
47589dc44ceSjose borrego  *	DWORD tod_year;      // current year
47689dc44ceSjose borrego  *	DWORD tod_weekday;   // day of the week since sunday [0-6]
47789dc44ceSjose borrego  * } TIME_OF_DAY_INFO;
47889dc44ceSjose borrego  *
47989dc44ceSjose borrego  * The time zone of the server is calculated in minutes from Greenwich
48089dc44ceSjose borrego  * Mean Time (GMT). For time zones west of Greenwich, the value is
48189dc44ceSjose borrego  * positive; for time zones east of Greenwich, the value is negative.
48289dc44ceSjose borrego  * A value of -1 indicates that the time zone is undefined.
48389dc44ceSjose borrego  *
48489dc44ceSjose borrego  * The clock tick value represents a resolution of one ten-thousandth
48589dc44ceSjose borrego  * (0.0001) second.
48689dc44ceSjose borrego  */
48789dc44ceSjose borrego int
srvsvc_net_remote_tod(char * server,char * domain,struct timeval * tv,struct tm * tm)48889dc44ceSjose borrego srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv,
48989dc44ceSjose borrego     struct tm *tm)
49089dc44ceSjose borrego {
49189dc44ceSjose borrego 	struct mslm_NetRemoteTOD	arg;
49289dc44ceSjose borrego 	struct mslm_TIME_OF_DAY_INFO	*tod;
49389dc44ceSjose borrego 	mlsvc_handle_t			handle;
49489dc44ceSjose borrego 	int				rc;
49589dc44ceSjose borrego 	int				opnum;
49689dc44ceSjose borrego 	int				len;
497a0aa776eSAlan Wright 	char				user[SMB_USERNAME_MAXLEN];
498a0aa776eSAlan Wright 
499a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
50089dc44ceSjose borrego 
50189dc44ceSjose borrego 	rc = srvsvc_open(server, domain, user, &handle);
50289dc44ceSjose borrego 	if (rc != 0)
50389dc44ceSjose borrego 		return (-1);
50489dc44ceSjose borrego 
50589dc44ceSjose borrego 	opnum = SRVSVC_OPNUM_NetRemoteTOD;
50689dc44ceSjose borrego 	bzero(&arg, sizeof (struct mslm_NetRemoteTOD));
50789dc44ceSjose borrego 
50889dc44ceSjose borrego 	len = strlen(server) + 4;
50989dc44ceSjose borrego 	arg.servername = ndr_rpc_malloc(&handle, len);
51089dc44ceSjose borrego 	if (arg.servername == NULL) {
51189dc44ceSjose borrego 		srvsvc_close(&handle);
51289dc44ceSjose borrego 		return (-1);
51389dc44ceSjose borrego 	}
51489dc44ceSjose borrego 
51589dc44ceSjose borrego 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
51689dc44ceSjose borrego 
51789dc44ceSjose borrego 	rc = ndr_rpc_call(&handle, opnum, &arg);
51889dc44ceSjose borrego 	if ((rc != 0) || (arg.status != 0)) {
51989dc44ceSjose borrego 		srvsvc_close(&handle);
52089dc44ceSjose borrego 		return (-1);
52189dc44ceSjose borrego 	}
52289dc44ceSjose borrego 
52389dc44ceSjose borrego 	/*
52489dc44ceSjose borrego 	 * We're assigning milliseconds to microseconds
52589dc44ceSjose borrego 	 * here but the value's not really relevant.
52689dc44ceSjose borrego 	 */
52789dc44ceSjose borrego 	tod = arg.bufptr;
52889dc44ceSjose borrego 
52989dc44ceSjose borrego 	if (tv) {
53089dc44ceSjose borrego 		tv->tv_sec = tod->tod_elapsedt;
53189dc44ceSjose borrego 		tv->tv_usec = tod->tod_msecs;
53289dc44ceSjose borrego 	}
53389dc44ceSjose borrego 
53489dc44ceSjose borrego 	if (tm) {
53589dc44ceSjose borrego 		tm->tm_sec = tod->tod_secs;
53689dc44ceSjose borrego 		tm->tm_min = tod->tod_mins;
53789dc44ceSjose borrego 		tm->tm_hour = tod->tod_hours;
53889dc44ceSjose borrego 		tm->tm_mday = tod->tod_day;
53989dc44ceSjose borrego 		tm->tm_mon = tod->tod_month - 1;
54089dc44ceSjose borrego 		tm->tm_year = tod->tod_year - 1900;
54189dc44ceSjose borrego 		tm->tm_wday = tod->tod_weekday;
54289dc44ceSjose borrego 	}
54389dc44ceSjose borrego 
54489dc44ceSjose borrego 	srvsvc_close(&handle);
54589dc44ceSjose borrego 	return (0);
54689dc44ceSjose borrego }
54789dc44ceSjose borrego 
54889dc44ceSjose borrego void
srvsvc_net_test(char * server,char * domain,char * netname)54989dc44ceSjose borrego srvsvc_net_test(char *server, char *domain, char *netname)
55089dc44ceSjose borrego {
551a0aa776eSAlan Wright 	smb_domainex_t di;
5521fcced4cSJordan Brown 	srvsvc_server_info_t svinfo;
55389dc44ceSjose borrego 
55489dc44ceSjose borrego 	(void) smb_tracef("%s %s %s", server, domain, netname);
55589dc44ceSjose borrego 
55689dc44ceSjose borrego 	if (smb_domain_getinfo(&di)) {
557*b3700b07SGordon Ross 		server = di.d_dci.dc_name;
558a0aa776eSAlan Wright 		domain = di.d_primary.di_nbname;
55989dc44ceSjose borrego 	}
56089dc44ceSjose borrego 
5611fcced4cSJordan Brown 	if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) {
5621fcced4cSJordan Brown 		smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x",
5631fcced4cSJordan Brown 		    svinfo.sv_name ? svinfo.sv_name : "NULL",
5641fcced4cSJordan Brown 		    svinfo.sv_comment ? svinfo.sv_comment : "NULL",
5651fcced4cSJordan Brown 		    svinfo.sv_version_major, svinfo.sv_version_minor,
5661fcced4cSJordan Brown 		    svinfo.sv_platform_id, svinfo.sv_type);
5671fcced4cSJordan Brown 
5681fcced4cSJordan Brown 		free(svinfo.sv_name);
5691fcced4cSJordan Brown 		free(svinfo.sv_comment);
5701fcced4cSJordan Brown 	}
5711fcced4cSJordan Brown 
57289dc44ceSjose borrego 	(void) srvsvc_net_share_get_info(server, domain, netname);
57389dc44ceSjose borrego #if 0
57489dc44ceSjose borrego 	/*
57589dc44ceSjose borrego 	 * The NetSessionEnum server-side definition was updated.
57689dc44ceSjose borrego 	 * Disabled until the client-side has been updated.
57789dc44ceSjose borrego 	 */
57889dc44ceSjose borrego 	(void) srvsvc_net_session_enum(server, domain, netname);
57989dc44ceSjose borrego #endif
58089dc44ceSjose borrego 	(void) srvsvc_net_connect_enum(server, domain, netname, 0);
58189dc44ceSjose borrego 	(void) srvsvc_net_connect_enum(server, domain, netname, 1);
58289dc44ceSjose borrego }
583