1c65bd2aff9cd61f35b41093c1ed4960f84a5b64
[samba.git] / source4 / lib / credentials.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Jelmer Vernooij 2005
5    Copyright (C) Tim Potter 2001
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "system/filesys.h"
24
25 const char *cli_credentials_get_username(struct cli_credentials *cred)
26 {
27         if (cred == NULL) {
28                 return NULL;
29         }
30
31         if (cred->username_obtained == CRED_CALLBACK) {
32                 cred->username = cred->username_cb(cred);
33                 cred->username_obtained = CRED_SPECIFIED;
34         }
35
36         return cred->username;
37 }
38
39 BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
40 {
41         if (obtained >= cred->username_obtained) {
42                 cred->username = talloc_strdup(cred, val);
43                 cred->username_obtained = obtained;
44                 return True;
45         }
46
47         return False;
48 }
49
50 const char *cli_credentials_get_password(struct cli_credentials *cred)
51 {
52         if (cred == NULL) {
53                 return NULL;
54         }
55         
56         if (cred->password_obtained == CRED_CALLBACK) {
57                 cred->password = cred->password_cb(cred);
58                 cred->password_obtained = CRED_SPECIFIED;
59         }
60
61         return cred->password;
62 }
63
64 BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
65 {
66         if (obtained >= cred->password_obtained) {
67                 cred->password = talloc_strdup(cred, val);
68                 cred->password_obtained = obtained;
69                 return True;
70         }
71
72         return False;
73 }
74
75 const char *cli_credentials_get_domain(struct cli_credentials *cred)
76 {
77         if (cred == NULL) {
78                 return NULL;
79         }
80
81         if (cred->domain_obtained == CRED_CALLBACK) {
82                 cred->domain = cred->domain_cb(cred);
83                 cred->domain_obtained = CRED_SPECIFIED;
84         }
85
86         return cred->domain;
87 }
88
89
90 BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
91 {
92         if (obtained >= cred->domain_obtained) {
93                 cred->domain = talloc_strdup(cred, val);
94                 cred->domain_obtained = obtained;
95                 return True;
96         }
97
98         return False;
99 }
100
101 const char *cli_credentials_get_realm(struct cli_credentials *cred)
102 {       
103         if (cred == NULL) {
104                 return NULL;
105         }
106
107         if (cred->realm_obtained == CRED_CALLBACK) {
108                 cred->realm = cred->realm_cb(cred);
109                 cred->realm_obtained = CRED_SPECIFIED;
110         }
111
112         return cred->realm;
113 }
114
115 BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
116 {
117         if (obtained >= cred->realm_obtained) {
118                 cred->realm = talloc_strdup(cred, val);
119                 cred->realm_obtained = obtained;
120                 return True;
121         }
122
123         return False;
124 }
125
126 const char *cli_credentials_get_workstation(struct cli_credentials *cred)
127 {
128         if (cred == NULL) {
129                 return NULL;
130         }
131
132         if (cred->workstation_obtained == CRED_CALLBACK) {
133                 cred->workstation = cred->workstation_cb(cred);
134                 cred->workstation_obtained = CRED_SPECIFIED;
135         }
136
137         return cred->workstation;
138 }
139
140 BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
141 {
142         if (obtained >= cred->workstation_obtained) {
143                 cred->workstation = talloc_strdup(cred, val);
144                 cred->workstation_obtained = obtained;
145                 return True;
146         }
147
148         return False;
149 }
150
151 BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained)
152 {
153         char *p;
154         char pass[128];
155
156         for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
157                 p && p - pass < sizeof(pass);) {
158                 switch (read(fd, p, 1)) {
159                 case 1:
160                         if (*p != '\n' && *p != '\0') {
161                                 *++p = '\0'; /* advance p, and null-terminate pass */
162                                 break;
163                         }
164                 case 0:
165                         if (p - pass) {
166                                 *p = '\0'; /* null-terminate it, just in case... */
167                                 p = NULL; /* then force the loop condition to become false */
168                                 break;
169                         } else {
170                                 fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n");
171                                 return False;
172                         }
173
174                 default:
175                         fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
176                                         fd, strerror(errno));
177                         return False;
178                 }
179         }
180
181         cli_credentials_set_password(credentials, pass, obtained);
182         return True;
183 }
184
185 BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
186 {
187         int fd = open(file, O_RDONLY, 0);
188         BOOL ret;
189
190         if (fd < 0) {
191                 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
192                                 file, strerror(errno));
193                 return False;
194         }
195
196         ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
197
198         close(fd);
199         
200         return ret;
201 }
202
203 BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) 
204 {
205         XFILE *auth;
206         char buf[128];
207         uint16_t len = 0;
208         char *ptr, *val, *param;
209
210         if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL)
211         {
212                 /* fail if we can't open the credentials file */
213                 d_printf("ERROR: Unable to open credentials file!\n");
214                 return False;
215         }
216
217         while (!x_feof(auth))
218         {
219                 /* get a line from the file */
220                 if (!x_fgets(buf, sizeof(buf), auth))
221                         continue;
222                 len = strlen(buf);
223
224                 if ((len) && (buf[len-1]=='\n'))
225                 {
226                         buf[len-1] = '\0';
227                         len--;
228                 }
229                 if (len == 0)
230                         continue;
231
232                 /* break up the line into parameter & value.
233                  * will need to eat a little whitespace possibly */
234                 param = buf;
235                 if (!(ptr = strchr_m (buf, '=')))
236                         continue;
237
238                 val = ptr+1;
239                 *ptr = '\0';
240
241                 /* eat leading white space */
242                 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
243                         val++;
244
245                 if (strwicmp("password", param) == 0) {
246                         cli_credentials_set_password(cred, val, obtained);
247                 } else if (strwicmp("username", param) == 0) {
248                         cli_credentials_set_username(cred, val, obtained);
249                 } else if (strwicmp("domain", param) == 0) {
250                         cli_credentials_set_domain(cred, val, obtained);
251                 } else if (strwicmp("realm", param) == 0) {
252                         cli_credentials_set_realm(cred, val, obtained);
253                 }
254                 memset(buf, 0, sizeof(buf));
255         }
256
257         x_fclose(auth);
258         return True;
259 }
260
261
262 void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
263 {
264         char *uname, *p;
265
266         uname = talloc_strdup(credentials, data); 
267         cli_credentials_set_username(credentials, uname, obtained);
268
269         if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) {
270                 *p = 0;
271                 cli_credentials_set_domain(credentials, uname, obtained);
272                 credentials->username = uname = p+1;
273         }
274
275         if ((p = strchr_m(uname,'@'))) {
276                 *p = 0;
277                 cli_credentials_set_realm(credentials, p+1, obtained);
278         }
279
280         if ((p = strchr_m(uname,'%'))) {
281                 *p = 0;
282                 cli_credentials_set_password(credentials, p+1, obtained);
283         }
284 }
285
286 void cli_credentials_guess(struct cli_credentials *cred)
287 {
288         char *p;
289
290         cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED);
291         cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED);
292         cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED);
293
294         if (getenv("LOGNAME")) {
295                 cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED);
296         }
297
298         if (getenv("USER")) {
299                 cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED);
300                 if ((p = strchr_m(getenv("USER"),'%'))) {
301                         *p = 0;
302                         memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cred->password));
303                 }
304         }
305
306         if (getenv("DOMAIN")) {
307                 cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESSED);
308         }
309
310         if (getenv("PASSWD")) {
311                 cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESSED);
312         }
313
314         if (getenv("PASSWD_FD")) {
315                 cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESSED);
316         }
317         
318         if (getenv("PASSWD_FILE")) {
319                 cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED);
320         }
321 }