2 Unix SMB/CIFS implementation.
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Tim Potter 2001
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
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.
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.
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.
24 #include "system/filesys.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "include/secrets.h"
27 #include "lib/ldb/include/ldb.h"
29 /* Create a new credentials structure, on the specified TALLOC_CTX */
30 struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
32 struct cli_credentails *cred = talloc_zero(mem_ctx, struct cli_credentials);
37 cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED);
38 cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED);
39 cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED);
44 const char *cli_credentials_get_username(struct cli_credentials *cred)
46 if (cred->username_obtained == CRED_CALLBACK) {
47 cred->username = cred->username_cb(cred);
48 cred->username_obtained = CRED_SPECIFIED;
51 return cred->username;
54 BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
56 if (obtained >= cred->username_obtained) {
57 cred->username = talloc_strdup(cred, val);
58 cred->username_obtained = obtained;
65 const char *cli_credentials_get_password(struct cli_credentials *cred)
67 if (cred->password_obtained == CRED_CALLBACK) {
68 cred->password = cred->password_cb(cred);
69 cred->password_obtained = CRED_SPECIFIED;
72 return cred->password;
75 BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
77 if (obtained >= cred->password_obtained) {
78 cred->password = talloc_strdup(cred, val);
79 cred->password_obtained = obtained;
86 const char *cli_credentials_get_domain(struct cli_credentials *cred)
88 if (cred->domain_obtained == CRED_CALLBACK) {
89 cred->domain = cred->domain_cb(cred);
90 cred->domain_obtained = CRED_SPECIFIED;
97 BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
99 if (obtained >= cred->domain_obtained) {
100 cred->domain = talloc_strdup(cred, val);
101 cred->domain_obtained = obtained;
108 const char *cli_credentials_get_realm(struct cli_credentials *cred)
114 if (cred->realm_obtained == CRED_CALLBACK) {
115 cred->realm = cred->realm_cb(cred);
116 cred->realm_obtained = CRED_SPECIFIED;
122 BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
124 if (obtained >= cred->realm_obtained) {
125 cred->realm = talloc_strdup(cred, val);
126 cred->realm_obtained = obtained;
133 const char *cli_credentials_get_workstation(struct cli_credentials *cred)
139 if (cred->workstation_obtained == CRED_CALLBACK) {
140 cred->workstation = cred->workstation_cb(cred);
141 cred->workstation_obtained = CRED_SPECIFIED;
144 return cred->workstation;
147 BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained)
149 if (obtained >= cred->workstation_obtained) {
150 cred->workstation = talloc_strdup(cred, val);
151 cred->workstation_obtained = obtained;
158 BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained)
163 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
164 p && p - pass < sizeof(pass);) {
165 switch (read(fd, p, 1)) {
167 if (*p != '\n' && *p != '\0') {
168 *++p = '\0'; /* advance p, and null-terminate pass */
173 *p = '\0'; /* null-terminate it, just in case... */
174 p = NULL; /* then force the loop condition to become false */
177 fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n");
182 fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
183 fd, strerror(errno));
188 cli_credentials_set_password(credentials, pass, obtained);
192 BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
194 int fd = open(file, O_RDONLY, 0);
198 fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
199 file, strerror(errno));
203 ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
210 BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained)
215 char *ptr, *val, *param;
217 if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL)
219 /* fail if we can't open the credentials file */
220 d_printf("ERROR: Unable to open credentials file!\n");
224 while (!x_feof(auth))
226 /* get a line from the file */
227 if (!x_fgets(buf, sizeof(buf), auth))
231 if ((len) && (buf[len-1]=='\n'))
239 /* break up the line into parameter & value.
240 * will need to eat a little whitespace possibly */
242 if (!(ptr = strchr_m (buf, '=')))
248 /* eat leading white space */
249 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
252 if (strwicmp("password", param) == 0) {
253 cli_credentials_set_password(cred, val, obtained);
254 } else if (strwicmp("username", param) == 0) {
255 cli_credentials_set_username(cred, val, obtained);
256 } else if (strwicmp("domain", param) == 0) {
257 cli_credentials_set_domain(cred, val, obtained);
258 } else if (strwicmp("realm", param) == 0) {
259 cli_credentials_set_realm(cred, val, obtained);
261 memset(buf, 0, sizeof(buf));
269 void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
273 uname = talloc_strdup(credentials, data);
274 if ((p = strchr_m(uname,'%'))) {
276 cli_credentials_set_password(credentials, p+1, obtained);
279 if ((p = strchr_m(uname,'@'))) {
281 cli_credentials_set_realm(credentials, p+1, obtained);
282 } else if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) {
284 cli_credentials_set_domain(credentials, uname, obtained);
287 cli_credentials_set_username(credentials, uname, obtained);
290 void cli_credentials_guess(struct cli_credentials *cred)
294 if (getenv("LOGNAME")) {
295 cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED);
298 if (getenv("USER")) {
299 cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED);
300 if ((p = strchr_m(getenv("USER"),'%'))) {
301 memset(p,0,strlen(cred->password));
305 if (getenv("DOMAIN")) {
306 cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESSED);
309 if (getenv("PASSWD")) {
310 cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESSED);
313 if (getenv("PASSWD_FD")) {
314 cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESSED);
317 if (getenv("PASSWD_FILE")) {
318 cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED);
322 NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds)
324 TALLOC_CTX *mem_ctx = talloc_named(creds, 0, "cli_credentials fetch machine password");
326 struct ldb_context *ldb;
328 struct ldb_message **msgs;
329 const char *base_dn = SECRETS_PRIMARY_DOMAIN_DN;
330 const char *attrs[] = {
336 const char *machine_account;
337 const char *password;
339 /* Local secrets are stored in secrets.ldb */
340 ldb = secrets_db_connect(mem_ctx);
342 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
345 /* search for the secret record */
346 ldb_ret = gendb_search(ldb,
347 mem_ctx, base_dn, &msgs, attrs,
348 SECRETS_PRIMARY_DOMAIN_FILTER,
349 cli_credentials_get_domain(creds));
351 DEBUG(1, ("Could not find join record to domain: %s\n",
353 talloc_free(mem_ctx);
354 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
355 } else if (ldb_ret != 1) {
356 talloc_free(mem_ctx);
357 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
360 password = ldb_msg_find_string(msgs[0], "secret", NULL);
362 DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n",
363 cli_credentials_get_domain(creds)));
364 talloc_free(mem_ctx);
365 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
368 machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL);
369 if (!machine_account) {
370 DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n",
371 cli_credentials_get_domain(creds)));
372 talloc_free(mem_ctx);
373 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
376 cli_credentials_set_username(creds, machine_account, CRED_SPECIFIED);
377 cli_credentials_set_password(creds, password, CRED_SPECIFIED);
378 talloc_free(mem_ctx);
383 /* Fill in a credentails structure as anonymous */
384 void cli_credentials_set_anonymous(struct cli_credentials *cred)
386 cli_credentials_set_username(cred, "", CRED_SPECIFIED);
387 cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
388 cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
391 BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials)
393 const char *username = cli_credentials_get_username(credentials);
395 if (!username || !username[0])