r5917: First step in using the new cli_credentials structure. This patch
[tprouty/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->username_obtained == CRED_CALLBACK) {
28                 cred->username = cred->username_cb(cred);
29                 cred->username_obtained = CRED_SPECIFIED;
30         }
31
32         return cred->username;
33 }
34
35 BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
36 {
37         if (obtained >= cred->username_obtained) {
38                 cred->username = talloc_strdup(cred, val);
39                 cred->username_obtained = obtained;
40                 return True;
41         }
42
43         return False;
44 }
45
46 const char *cli_credentials_get_password(struct cli_credentials *cred)
47 {
48         if (cred->password_obtained == CRED_CALLBACK) {
49                 cred->password = cred->password_cb(cred);
50                 cred->password_obtained = CRED_SPECIFIED;
51         }
52
53         return cred->password;
54 }
55
56 BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
57 {
58         if (obtained >= cred->password_obtained) {
59                 cred->password = talloc_strdup(cred, val);
60                 cred->password_obtained = obtained;
61                 return True;
62         }
63
64         return False;
65 }
66
67 const char *cli_credentials_get_domain(struct cli_credentials *cred)
68 {
69         if (cred->domain_obtained == CRED_CALLBACK) {
70                 cred->domain = cred->domain_cb(cred);
71                 cred->domain_obtained = CRED_SPECIFIED;
72         }
73
74         return cred->domain;
75 }
76
77
78 BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
79 {
80         if (obtained >= cred->domain_obtained) {
81                 cred->domain = talloc_strdup(cred, val);
82                 cred->domain_obtained = obtained;
83                 return True;
84         }
85
86         return False;
87 }
88
89 const char *cli_credentials_get_realm(struct cli_credentials *cred)
90 {
91         if (cred->realm_obtained == CRED_CALLBACK) {
92                 cred->realm = cred->realm_cb(cred);
93                 cred->realm_obtained = CRED_SPECIFIED;
94         }
95
96         return cred->realm;
97 }
98
99 BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
100 {
101         if (obtained >= cred->realm_obtained) {
102                 cred->realm = talloc_strdup(cred, val);
103                 cred->realm_obtained = obtained;
104                 return True;
105         }
106
107         return False;
108 }
109
110 const char *cli_credentials_get_workstation(struct cli_credentials *cred)
111 {
112         if (cred->workstation_obtained == CRED_CALLBACK) {
113                 cred->workstation = cred->workstation_cb(cred);
114                 cred->workstation_obtained = CRED_SPECIFIED;
115         }
116
117         return cred->workstation;
118 }
119
120 BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
121 {
122         if (obtained >= cred->workstation_obtained) {
123                 cred->workstation = talloc_strdup(cred, val);
124                 cred->workstation_obtained = obtained;
125                 return True;
126         }
127
128         return False;
129 }
130
131 BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained)
132 {
133         char *p;
134         char pass[128];
135
136         for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
137                 p && p - pass < sizeof(pass);) {
138                 switch (read(fd, p, 1)) {
139                 case 1:
140                         if (*p != '\n' && *p != '\0') {
141                                 *++p = '\0'; /* advance p, and null-terminate pass */
142                                 break;
143                         }
144                 case 0:
145                         if (p - pass) {
146                                 *p = '\0'; /* null-terminate it, just in case... */
147                                 p = NULL; /* then force the loop condition to become false */
148                                 break;
149                         } else {
150                                 fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n");
151                                 return False;
152                         }
153
154                 default:
155                         fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
156                                         fd, strerror(errno));
157                         return False;
158                 }
159         }
160
161         cli_credentials_set_password(credentials, pass, obtained);
162         return True;
163 }
164
165 BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
166 {
167         int fd = open(file, O_RDONLY, 0);
168         BOOL ret;
169
170         if (fd < 0) {
171                 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
172                                 file, strerror(errno));
173                 return False;
174         }
175
176         ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
177
178         close(fd);
179         
180         return ret;
181 }
182
183 BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) 
184 {
185         XFILE *auth;
186         char buf[128];
187         uint16_t len = 0;
188         char *ptr, *val, *param;
189
190         if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL)
191         {
192                 /* fail if we can't open the credentials file */
193                 d_printf("ERROR: Unable to open credentials file!\n");
194                 return False;
195         }
196
197         while (!x_feof(auth))
198         {
199                 /* get a line from the file */
200                 if (!x_fgets(buf, sizeof(buf), auth))
201                         continue;
202                 len = strlen(buf);
203
204                 if ((len) && (buf[len-1]=='\n'))
205                 {
206                         buf[len-1] = '\0';
207                         len--;
208                 }
209                 if (len == 0)
210                         continue;
211
212                 /* break up the line into parameter & value.
213                  * will need to eat a little whitespace possibly */
214                 param = buf;
215                 if (!(ptr = strchr_m (buf, '=')))
216                         continue;
217
218                 val = ptr+1;
219                 *ptr = '\0';
220
221                 /* eat leading white space */
222                 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
223                         val++;
224
225                 if (strwicmp("password", param) == 0) {
226                         cli_credentials_set_password(cred, val, obtained);
227                 } else if (strwicmp("username", param) == 0) {
228                         cli_credentials_set_username(cred, val, obtained);
229                 } else if (strwicmp("domain", param) == 0) {
230                         cli_credentials_set_domain(cred, val, obtained);
231                 } else if (strwicmp("realm", param) == 0) {
232                         cli_credentials_set_realm(cred, val, obtained);
233                 }
234                 memset(buf, 0, sizeof(buf));
235         }
236
237         x_fclose(auth);
238         return True;
239 }
240
241
242 void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
243 {
244         char *uname, *p;
245
246         uname = talloc_strdup(credentials, data); 
247         cli_credentials_set_username(credentials, uname, obtained);
248
249         if ((p = strchr_m(uname,'\\'))) {
250                 *p = 0;
251                 cli_credentials_set_domain(credentials, uname, obtained);
252                 credentials->username = uname = p+1;
253         }
254
255         if ((p = strchr_m(uname,'@'))) {
256                 *p = 0;
257                 cli_credentials_set_realm(credentials, p+1, obtained);
258         }
259
260         if ((p = strchr_m(uname,'%'))) {
261                 *p = 0;
262                 cli_credentials_set_password(credentials, p+1, obtained);
263         }
264 }
265
266 void cli_credentials_guess(struct cli_credentials *cred)
267 {
268         char *p;
269
270         cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED);
271         cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED);
272         cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED);
273
274         if (getenv("LOGNAME")) {
275                 cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED);
276         }
277
278         if (getenv("USER")) {
279                 cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED);
280                 if ((p = strchr_m(getenv("USER"),'%'))) {
281                         *p = 0;
282                         memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cred->password));
283                 }
284         }
285
286         if (getenv("DOMAIN")) {
287                 cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESSED);
288         }
289
290         if (getenv("PASSWD")) {
291                 cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESSED);
292         }
293
294         if (getenv("PASSWD_FD")) {
295                 cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESSED);
296         }
297         
298         if (getenv("PASSWD_FILE")) {
299                 cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED);
300         }
301 }