1/*
2   Use Samba mechanisms to authenticate a domain user.
3
4   This program is written to cooperate with the Unix SMB/CIFS implementation.
5
6   Copyright (C) Broadcom Corporation              2004
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include "includes.h"
24
25
26#define max(a,b) ((a)>(b)?(a):(b))
27
28static void
29setup()
30{
31	pstring configfile;
32	pstrcpy(configfile, dyn_CONFIGFILE);
33
34	if (!lp_load(configfile,True,False,False)) {
35		fprintf(stderr, "Can't load %s - run testparm to debug it\n",
36			dyn_CONFIGFILE);
37		exit(2);
38	}
39
40	setup_logging("smbauth", True);
41}
42
43
44/*********************************************************
45 Start here.
46**********************************************************/
47int main(int argc, char **argv)
48{
49	int result = 0;
50	const char * user_name;
51	const char * password;
52	const char * domain_name;
53	fstring pdc_name;
54	const char * local_machine_name;
55	size_t pdc_name_len;
56	size_t machine_name_len;
57	size_t max_name_len;
58	size_t len;
59	const char * format = "/usr/local/samba/bin/smbclient -L %s -U%s%%%s -c quit > /dev/null 2>/dev/null";
60	struct in_addr pdc_addr;
61	const struct passwd * pwent;
62
63
64	/*
65		Handle command line arguments.
66	 */
67	if (argc != 3)
68	{
69		printf("Usage: %s <user> <password>\n", argv[0]);
70		printf("\tUse a colon (':') to indicate a null password.\n");
71		exit(1);
72	}
73	user_name = argv[1];
74	password = argv[2];
75	if (strcmp(password, ":") == 0)
76		password = NULL;
77
78
79	/*
80		Do some Samba related initialization.
81	 */
82	setup();
83	load_interfaces();
84
85	/*
86	 * Set the machine NETBIOS name if not already
87	 * set from the config file.
88	 */
89	if (!init_names())
90		return 1;
91
92
93	/*
94		Get information about the PDC.
95	 */
96	domain_name = lp_workgroup();
97	if (!get_dc_name(domain_name, NULL, pdc_name, &pdc_addr))
98	{
99		fprintf(stderr, "ERROR: Cannot get the PDC name for domain %s.\n", domain_name);
100		return 2;
101	}
102
103	//printf("smbauth: domain=%s pdc=%s\n", domain_name, pdc_name);
104
105//	local_machine_name = get_local_machine_name();
106//	if (local_machine_name == NULL)
107//	{
108//		fprintf(stderr, "ERROR: Cannot get the local machine name.\n");
109//		return 3;
110//	}
111
112
113	/*
114		Allocate buffer to hold the command.
115	 */
116	pdc_name_len = strlen(pdc_name);
117	machine_name_len = strlen(local_machine_name);
118	max_name_len = 16; //max(pdc_name_len, machine_name_len);
119
120	len = strlen(format) + max_name_len + strlen(user_name) + strlen(password) + 32;
121	char *cmd = (char *)malloc(len);
122	if (cmd == NULL)
123	{
124		fprintf(stderr, "ERROR: Cannot allocate memory for command string.\n");
125		free(cmd);
126		return 4;
127	}
128
129
130	/*
131		Authenticate the user by going to the domain server.
132
133		For unknown reasons, smbclient run against the local machine does not
134		properly authenticate users.  So, running it against the domain controller
135		does.
136	 */
137	smb_snprintf(cmd, len, format, inet_ntoa(pdc_addr), user_name, password);
138	//printf("smbauth: cmd='%s'\n", cmd);
139	result = smbrun(cmd, NULL);
140	if (result != 0)
141	{
142		fprintf(stderr, "ERROR: Could not authenticate %s on PDC %s.\n", user_name, pdc_name);
143		free(cmd);
144		return 5;
145	}
146
147
148	/*
149		This domain member keeps an entry in its own /etc/passwd file.  This
150		is not for authentication.  It merely holds the uid and gid for this
151		user; Samba always authenticates against the domain controller.
152		Because the calls to smbclient for the purposes of creating this
153		/etc/passwd entry are numerous and slow, we short-circuit this
154		procedure if the user is already in our local password file.
155	 */
156	pwent = getpwnam(user_name);
157	if (pwent != NULL)
158	{
159		//printf("smbauth: short-circuited caching for %s\n", pwent->pw_name);
160		free(cmd);
161		return 0;
162	}
163	//printf("smbauth: caching uid/gid for %s\n", user_name);
164
165
166	/*
167		Cache the account information from the domain server to this domain
168		member.  This is important because the caching process assigns the
169		local UID and GID to this user.
170
171		For unknown reasons, the password must be null.
172	 */
173	smb_snprintf(cmd, len, format, "127.0.0.1"/*local_machine_name*/, user_name, "" /*password*/);
174	//printf("smbauth: cmd='%s'\n", cmd);
175	result = smbrun(cmd, NULL);
176	if (result != 0)
177	{
178		fprintf(stderr, "ERROR: Could not cache %s on local machine.\n", user_name);
179		free(cmd);
180		return 6;
181	}
182
183
184	/*
185		Oh, this just keeps getting better.  Sometimes, smbcontrol won't work
186		with a password, and sometimes it won't work without one.   So,
187		we're tring all the options.  To make this fun, smbcontrol never gives
188		me an error code, so I won't know which if any actually works.  Grrrr.
189
190		Try a second time to cache the account information from the domain
191		server to this domain member.  This is important because the caching
192		process assigns the local UID and GID to this user.
193	 */
194	smb_snprintf(cmd, len, format, "127.0.0.1"/*local_machine_name*/, user_name, password);
195	//printf("smbauth: cmd='%s'\n", cmd);
196	result = smbrun(cmd, NULL);
197	if (result != 0)
198	{
199		fprintf(stderr, "ERROR: Could not cache %s on local machine (2nd try).\n", user_name);
200		free(cmd);
201		return 7;
202	}
203
204
205	free(cmd);
206	return result;
207}
208