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