Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : User credentials handling
5 :
6 : Copyright (C) Jelmer Vernooij 2005
7 : Copyright (C) Tim Potter 2001
8 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "lib/util/util_file.h"
26 : #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
27 : #include "auth/credentials/credentials.h"
28 : #include "auth/credentials/credentials_internal.h"
29 : #include "auth/gensec/gensec.h"
30 : #include "libcli/auth/libcli_auth.h"
31 : #include "tevent.h"
32 : #include "param/param.h"
33 : #include "system/filesys.h"
34 : #include "system/passwd.h"
35 :
36 : /**
37 : * Create a new credentials structure
38 : * @param mem_ctx TALLOC_CTX parent for credentials structure
39 : */
40 360473 : _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
41 : {
42 360473 : struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials);
43 360473 : if (cred == NULL) {
44 0 : return cred;
45 : }
46 :
47 360473 : cred->winbind_separator = '\\';
48 :
49 360473 : cred->kerberos_state = CRED_USE_KERBEROS_DESIRED;
50 :
51 360473 : cred->signing_state = SMB_SIGNING_DEFAULT;
52 :
53 : /*
54 : * The default value of lpcfg_client_ipc_signing() is REQUIRED, so use
55 : * the same value here.
56 : */
57 360473 : cred->ipc_signing_state = SMB_SIGNING_REQUIRED;
58 360473 : cred->encryption_state = SMB_ENCRYPTION_DEFAULT;
59 :
60 360473 : return cred;
61 : }
62 :
63 : _PUBLIC_
64 62812 : struct cli_credentials *cli_credentials_init_server(TALLOC_CTX *mem_ctx,
65 : struct loadparm_context *lp_ctx)
66 : {
67 62812 : struct cli_credentials *server_creds = NULL;
68 2633 : NTSTATUS status;
69 2633 : bool ok;
70 :
71 62812 : server_creds = cli_credentials_init(mem_ctx);
72 62812 : if (server_creds == NULL) {
73 0 : return NULL;
74 : }
75 :
76 62812 : ok = cli_credentials_set_conf(server_creds, lp_ctx);
77 62812 : if (!ok) {
78 0 : TALLOC_FREE(server_creds);
79 0 : return NULL;
80 : }
81 :
82 62812 : status = cli_credentials_set_machine_account(server_creds, lp_ctx);
83 62812 : if (!NT_STATUS_IS_OK(status)) {
84 2 : DEBUG(1, ("Failed to obtain server credentials: %s\n",
85 : nt_errstr(status)));
86 2 : TALLOC_FREE(server_creds);
87 2 : return NULL;
88 : }
89 :
90 60177 : return server_creds;
91 : }
92 :
93 0 : _PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred,
94 : void *callback_data)
95 : {
96 0 : cred->priv_data = callback_data;
97 0 : }
98 :
99 0 : _PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred)
100 : {
101 0 : return cred->priv_data;
102 : }
103 :
104 : /**
105 : * Create a new anonymous credential
106 : * @param mem_ctx TALLOC_CTX parent for credentials structure
107 : */
108 119525 : _PUBLIC_ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx)
109 : {
110 1892 : struct cli_credentials *anon_credentials;
111 :
112 119525 : anon_credentials = cli_credentials_init(mem_ctx);
113 119525 : cli_credentials_set_anonymous(anon_credentials);
114 :
115 119525 : return anon_credentials;
116 : }
117 :
118 282120 : _PUBLIC_ bool cli_credentials_set_kerberos_state(struct cli_credentials *creds,
119 : enum credentials_use_kerberos kerberos_state,
120 : enum credentials_obtained obtained)
121 : {
122 282120 : if (obtained >= creds->kerberos_state_obtained) {
123 282119 : creds->kerberos_state = kerberos_state;
124 282119 : creds->kerberos_state_obtained = obtained;
125 :
126 282119 : return true;
127 : }
128 :
129 0 : return false;
130 : }
131 :
132 0 : _PUBLIC_ void cli_credentials_set_forced_sasl_mech(struct cli_credentials *creds,
133 : const char *sasl_mech)
134 : {
135 0 : TALLOC_FREE(creds->forced_sasl_mech);
136 0 : creds->forced_sasl_mech = talloc_strdup(creds, sasl_mech);
137 0 : }
138 :
139 79 : _PUBLIC_ void cli_credentials_set_krb_forwardable(struct cli_credentials *creds,
140 : enum credentials_krb_forwardable krb_forwardable)
141 : {
142 79 : creds->krb_forwardable = krb_forwardable;
143 79 : }
144 :
145 719372 : _PUBLIC_ enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds)
146 : {
147 719372 : return creds->kerberos_state;
148 : }
149 :
150 416767 : _PUBLIC_ const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *creds)
151 : {
152 416767 : return creds->forced_sasl_mech;
153 : }
154 :
155 15543 : _PUBLIC_ enum credentials_krb_forwardable cli_credentials_get_krb_forwardable(struct cli_credentials *creds)
156 : {
157 15543 : return creds->krb_forwardable;
158 : }
159 :
160 43590 : _PUBLIC_ bool cli_credentials_set_gensec_features(struct cli_credentials *creds,
161 : uint32_t gensec_features,
162 : enum credentials_obtained obtained)
163 : {
164 43590 : if (obtained >= creds->gensec_features_obtained) {
165 43589 : creds->gensec_features_obtained = obtained;
166 43589 : creds->gensec_features = gensec_features;
167 :
168 43589 : return true;
169 : }
170 :
171 0 : return false;
172 : }
173 :
174 347026 : _PUBLIC_ uint32_t cli_credentials_get_gensec_features(struct cli_credentials *creds)
175 : {
176 347026 : return creds->gensec_features;
177 : }
178 :
179 :
180 : /**
181 : * Obtain the username for this credentials context.
182 : * @param cred credentials context
183 : * @retval The username set on this context.
184 : * @note Return value will never be NULL except by programmer error.
185 : */
186 1559425 : _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred)
187 : {
188 1559425 : if (cred->machine_account_pending) {
189 0 : cli_credentials_set_machine_account(cred,
190 : cred->machine_account_pending_lp_ctx);
191 : }
192 :
193 1559425 : if (cred->username_obtained == CRED_CALLBACK &&
194 0 : !cred->callback_running) {
195 0 : cred->callback_running = true;
196 0 : cred->username = cred->username_cb(cred);
197 0 : cred->callback_running = false;
198 0 : if (cred->username_obtained == CRED_CALLBACK) {
199 0 : cred->username_obtained = CRED_CALLBACK_RESULT;
200 0 : cli_credentials_invalidate_ccache(cred, cred->username_obtained);
201 : }
202 : }
203 :
204 1559425 : return cred->username;
205 : }
206 :
207 : /**
208 : * @brief Obtain the username for this credentials context.
209 : *
210 : * @param[in] cred The credential context.
211 : *
212 : * @param[in] obtained A pointer to store the obtained information.
213 : *
214 : * return The user name or NULL if an error occurred.
215 : */
216 : _PUBLIC_ const char *
217 24832 : cli_credentials_get_username_and_obtained(struct cli_credentials *cred,
218 : enum credentials_obtained *obtained)
219 : {
220 24832 : if (obtained != NULL) {
221 24832 : *obtained = cred->username_obtained;
222 : }
223 :
224 24832 : return cli_credentials_get_username(cred);
225 : }
226 :
227 817237 : _PUBLIC_ bool cli_credentials_set_username(struct cli_credentials *cred,
228 : const char *val, enum credentials_obtained obtained)
229 : {
230 817237 : if (obtained >= cred->username_obtained) {
231 684118 : cred->username = talloc_strdup(cred, val);
232 684118 : cred->username_obtained = obtained;
233 684118 : cli_credentials_invalidate_ccache(cred, cred->username_obtained);
234 684118 : return true;
235 : }
236 :
237 132943 : return false;
238 : }
239 :
240 0 : _PUBLIC_ bool cli_credentials_set_username_callback(struct cli_credentials *cred,
241 : const char *(*username_cb) (struct cli_credentials *))
242 : {
243 0 : if (cred->username_obtained < CRED_CALLBACK) {
244 0 : cred->username_cb = username_cb;
245 0 : cred->username_obtained = CRED_CALLBACK;
246 0 : return true;
247 : }
248 :
249 0 : return false;
250 : }
251 :
252 605 : _PUBLIC_ bool cli_credentials_set_bind_dn(struct cli_credentials *cred,
253 : const char *bind_dn)
254 : {
255 605 : cred->bind_dn = talloc_strdup(cred, bind_dn);
256 605 : return true;
257 : }
258 :
259 : /**
260 : * Obtain the BIND DN for this credentials context.
261 : * @param cred credentials context
262 : * @retval The username set on this context.
263 : * @note Return value will be NULL if not specified explicitly
264 : */
265 28100 : _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
266 : {
267 28100 : return cred->bind_dn;
268 : }
269 :
270 :
271 : /**
272 : * Obtain the client principal for this credentials context.
273 : * @param cred credentials context
274 : * @retval The username set on this context.
275 : * @note Return value will never be NULL except by programmer error.
276 : */
277 89074 : _PUBLIC_ char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
278 : {
279 89074 : if (cred->machine_account_pending) {
280 0 : cli_credentials_set_machine_account(cred,
281 : cred->machine_account_pending_lp_ctx);
282 : }
283 :
284 89074 : if (cred->principal_obtained == CRED_CALLBACK &&
285 0 : !cred->callback_running) {
286 0 : cred->callback_running = true;
287 0 : cred->principal = cred->principal_cb(cred);
288 0 : cred->callback_running = false;
289 0 : if (cred->principal_obtained == CRED_CALLBACK) {
290 0 : cred->principal_obtained = CRED_CALLBACK_RESULT;
291 0 : cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
292 : }
293 : }
294 :
295 89074 : if (cred->principal_obtained < cred->username_obtained
296 5606 : || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
297 83476 : const char *effective_username = NULL;
298 83476 : const char *effective_realm = NULL;
299 2754 : enum credentials_obtained effective_obtained;
300 :
301 83476 : effective_username = cli_credentials_get_username(cred);
302 83476 : if (effective_username == NULL || strlen(effective_username) == 0) {
303 7 : *obtained = cred->username_obtained;
304 7 : return NULL;
305 : }
306 :
307 83469 : if (cred->domain_obtained > cred->realm_obtained) {
308 18743 : effective_realm = cli_credentials_get_domain(cred);
309 18743 : effective_obtained = MIN(cred->domain_obtained,
310 : cred->username_obtained);
311 : } else {
312 64726 : effective_realm = cli_credentials_get_realm(cred);
313 64726 : effective_obtained = MIN(cred->realm_obtained,
314 : cred->username_obtained);
315 : }
316 :
317 83469 : if (effective_realm == NULL || strlen(effective_realm) == 0) {
318 97 : effective_realm = cli_credentials_get_domain(cred);
319 97 : effective_obtained = MIN(cred->domain_obtained,
320 : cred->username_obtained);
321 : }
322 :
323 83469 : if (effective_realm != NULL && strlen(effective_realm) != 0) {
324 83405 : *obtained = effective_obtained;
325 83405 : return talloc_asprintf(mem_ctx, "%s@%s",
326 : effective_username,
327 : effective_realm);
328 : }
329 : }
330 5662 : *obtained = cred->principal_obtained;
331 5662 : return talloc_strdup(mem_ctx, cred->principal);
332 : }
333 :
334 : /**
335 : * Obtain the client principal for this credentials context.
336 : * @param cred credentials context
337 : * @retval The username set on this context.
338 : * @note Return value will never be NULL except by programmer error.
339 : */
340 23072 : _PUBLIC_ char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
341 : {
342 556 : enum credentials_obtained obtained;
343 23072 : return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
344 : }
345 :
346 213315 : _PUBLIC_ bool cli_credentials_set_principal(struct cli_credentials *cred,
347 : const char *val,
348 : enum credentials_obtained obtained)
349 : {
350 213315 : if (obtained >= cred->principal_obtained) {
351 213290 : cred->principal = talloc_strdup(cred, val);
352 213290 : if (cred->principal == NULL) {
353 161524 : return false;
354 : }
355 49427 : cred->principal_obtained = obtained;
356 :
357 49427 : cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
358 49427 : return true;
359 : }
360 :
361 25 : return false;
362 : }
363 :
364 : /* Set a callback to get the principal. This could be a popup dialog,
365 : * a terminal prompt or similar. */
366 0 : _PUBLIC_ bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
367 : const char *(*principal_cb) (struct cli_credentials *))
368 : {
369 0 : if (cred->principal_obtained < CRED_CALLBACK) {
370 0 : cred->principal_cb = principal_cb;
371 0 : cred->principal_obtained = CRED_CALLBACK;
372 0 : return true;
373 : }
374 :
375 0 : return false;
376 : }
377 :
378 : /* Some of our tools are 'anonymous by default'. This is a single
379 : * function to determine if authentication has been explicitly
380 : * requested */
381 :
382 54532 : _PUBLIC_ bool cli_credentials_authentication_requested(struct cli_credentials *cred)
383 : {
384 54532 : uint32_t gensec_features = 0;
385 :
386 54532 : if (cred->bind_dn) {
387 442 : return true;
388 : }
389 :
390 : /*
391 : * If we forced the mech we clearly want authentication. E.g. to use
392 : * SASL/EXTERNAL which has no credentials.
393 : */
394 54090 : if (cred->forced_sasl_mech) {
395 0 : return true;
396 : }
397 :
398 54090 : if (cli_credentials_is_anonymous(cred)){
399 1187 : return false;
400 : }
401 :
402 52901 : if (cred->principal_obtained >= CRED_SPECIFIED) {
403 12656 : return true;
404 : }
405 40150 : if (cred->username_obtained >= CRED_SPECIFIED) {
406 35815 : return true;
407 : }
408 :
409 4293 : if (cli_credentials_get_kerberos_state(cred) == CRED_USE_KERBEROS_REQUIRED) {
410 14 : return true;
411 : }
412 :
413 4279 : gensec_features = cli_credentials_get_gensec_features(cred);
414 4279 : if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
415 0 : return true;
416 : }
417 :
418 4279 : if (gensec_features & GENSEC_FEATURE_SIGN) {
419 0 : return true;
420 : }
421 :
422 4279 : if (gensec_features & GENSEC_FEATURE_SEAL) {
423 0 : return true;
424 : }
425 :
426 4258 : return false;
427 : }
428 :
429 : /**
430 : * Obtain the password for this credentials context.
431 : * @param cred credentials context
432 : * @retval If set, the cleartext password, otherwise NULL
433 : */
434 231404 : _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred)
435 : {
436 231404 : if (cred->machine_account_pending) {
437 1 : cli_credentials_set_machine_account(cred,
438 : cred->machine_account_pending_lp_ctx);
439 : }
440 :
441 231404 : if (cred->password_obtained == CRED_CALLBACK &&
442 39 : !cred->callback_running &&
443 39 : !cred->password_will_be_nt_hash) {
444 39 : cred->callback_running = true;
445 39 : cred->password = cred->password_cb(cred);
446 39 : cred->callback_running = false;
447 39 : if (cred->password_obtained == CRED_CALLBACK) {
448 39 : cred->password_obtained = CRED_CALLBACK_RESULT;
449 39 : cli_credentials_invalidate_ccache(cred, cred->password_obtained);
450 : }
451 : }
452 :
453 231404 : return cred->password;
454 : }
455 :
456 : /**
457 : * @brief Obtain the password for this credentials context.
458 : *
459 : * @param[in] cred The credential context.
460 : *
461 : * @param[in] obtained A pointer to store the obtained information.
462 : *
463 : * return The user name or NULL if an error occurred.
464 : */
465 : _PUBLIC_ const char *
466 21422 : cli_credentials_get_password_and_obtained(struct cli_credentials *cred,
467 : enum credentials_obtained *obtained)
468 : {
469 21422 : const char *password = cli_credentials_get_password(cred);
470 :
471 21422 : if (obtained != NULL) {
472 21422 : *obtained = cred->password_obtained;
473 : }
474 :
475 21422 : return password;
476 : }
477 :
478 : /* Set a password on the credentials context, including an indication
479 : * of 'how' the password was obtained */
480 :
481 283079 : _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred,
482 : const char *val,
483 : enum credentials_obtained obtained)
484 : {
485 283079 : if (obtained >= cred->password_obtained) {
486 :
487 283036 : cred->lm_response = data_blob_null;
488 283036 : cred->nt_response = data_blob_null;
489 283036 : cred->nt_hash = NULL;
490 283036 : cred->password = NULL;
491 :
492 283036 : cli_credentials_invalidate_ccache(cred, obtained);
493 :
494 283036 : cred->password_tries = 0;
495 :
496 283036 : if (val == NULL) {
497 164247 : cred->password_obtained = obtained;
498 164247 : return true;
499 : }
500 :
501 118789 : if (cred->password_will_be_nt_hash) {
502 3 : struct samr_Password *nt_hash = NULL;
503 3 : size_t val_len = strlen(val);
504 1 : size_t converted;
505 :
506 3 : nt_hash = talloc(cred, struct samr_Password);
507 3 : if (nt_hash == NULL) {
508 0 : return false;
509 : }
510 :
511 3 : converted = strhex_to_str((char *)nt_hash->hash,
512 : sizeof(nt_hash->hash),
513 : val, val_len);
514 3 : if (converted != sizeof(nt_hash->hash)) {
515 0 : TALLOC_FREE(nt_hash);
516 0 : return false;
517 : }
518 :
519 3 : cred->nt_hash = nt_hash;
520 3 : cred->password_obtained = obtained;
521 3 : return true;
522 : }
523 :
524 118786 : cred->password = talloc_strdup(cred, val);
525 118786 : if (cred->password == NULL) {
526 0 : return false;
527 : }
528 :
529 : /* Don't print the actual password in talloc memory dumps */
530 118786 : talloc_set_name_const(cred->password,
531 : "password set via cli_credentials_set_password");
532 118786 : cred->password_obtained = obtained;
533 :
534 118786 : return true;
535 : }
536 :
537 36 : return false;
538 : }
539 :
540 17991 : _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred,
541 : const char *(*password_cb) (struct cli_credentials *))
542 : {
543 17991 : if (cred->password_obtained < CRED_CALLBACK) {
544 11119 : cred->password_tries = 3;
545 11119 : cred->password_cb = password_cb;
546 11119 : cred->password_obtained = CRED_CALLBACK;
547 11119 : cli_credentials_invalidate_ccache(cred, cred->password_obtained);
548 11119 : return true;
549 : }
550 :
551 6872 : return false;
552 : }
553 :
554 : /**
555 : * Obtain the 'old' password for this credentials context (used for join accounts).
556 : * @param cred credentials context
557 : * @retval If set, the cleartext password, otherwise NULL
558 : */
559 533 : _PUBLIC_ const char *cli_credentials_get_old_password(struct cli_credentials *cred)
560 : {
561 533 : if (cred->machine_account_pending) {
562 0 : cli_credentials_set_machine_account(cred,
563 : cred->machine_account_pending_lp_ctx);
564 : }
565 :
566 533 : return cred->old_password;
567 : }
568 :
569 595 : _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
570 : const char *val,
571 : enum credentials_obtained obtained)
572 : {
573 595 : cred->old_password = talloc_strdup(cred, val);
574 595 : if (cred->old_password) {
575 : /* Don't print the actual password in talloc memory dumps */
576 309 : talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
577 : }
578 595 : cred->old_nt_hash = NULL;
579 595 : return true;
580 : }
581 :
582 : /**
583 : * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
584 : *
585 : * Sometimes we only have this much of the password, while the rest of
586 : * the time this call avoids calling E_md4hash themselves.
587 : *
588 : * @param cred credentials context
589 : * @retval If set, the cleartext password, otherwise NULL
590 : */
591 43536 : _PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
592 : TALLOC_CTX *mem_ctx)
593 : {
594 705 : enum credentials_obtained password_obtained;
595 705 : enum credentials_obtained ccache_threshold;
596 705 : enum credentials_obtained client_gss_creds_threshold;
597 705 : bool password_is_nt_hash;
598 43536 : const char *password = NULL;
599 43536 : struct samr_Password *nt_hash = NULL;
600 :
601 43536 : if (cred->nt_hash != NULL) {
602 : /*
603 : * If we already have a hash it's easy.
604 : */
605 14233 : goto return_hash;
606 : }
607 :
608 : /*
609 : * This is a bit tricky, with password_will_be_nt_hash
610 : * we still need to get the value via the password_callback
611 : * but if we did that we should not remember it's state
612 : * in the long run so we need to undo it.
613 : */
614 :
615 29303 : password_obtained = cred->password_obtained;
616 29303 : ccache_threshold = cred->ccache_threshold;
617 29303 : client_gss_creds_threshold = cred->client_gss_creds_threshold;
618 29303 : password_is_nt_hash = cred->password_will_be_nt_hash;
619 :
620 29303 : cred->password_will_be_nt_hash = false;
621 29303 : password = cli_credentials_get_password(cred);
622 :
623 29303 : cred->password_will_be_nt_hash = password_is_nt_hash;
624 29303 : if (password_is_nt_hash && password_obtained == CRED_CALLBACK) {
625 : /*
626 : * We got the nt_hash as string via the callback,
627 : * so we need to undo the state change.
628 : *
629 : * And also don't remember it as plaintext password.
630 : */
631 0 : cred->client_gss_creds_threshold = client_gss_creds_threshold;
632 0 : cred->ccache_threshold = ccache_threshold;
633 0 : cred->password_obtained = password_obtained;
634 0 : cred->password = NULL;
635 : }
636 :
637 29303 : if (password == NULL) {
638 1125 : return NULL;
639 : }
640 :
641 28168 : nt_hash = talloc(cred, struct samr_Password);
642 28168 : if (nt_hash == NULL) {
643 0 : return NULL;
644 : }
645 :
646 28168 : if (password_is_nt_hash) {
647 0 : size_t password_len = strlen(password);
648 0 : size_t converted;
649 :
650 0 : converted = strhex_to_str((char *)nt_hash->hash,
651 : sizeof(nt_hash->hash),
652 : password, password_len);
653 0 : if (converted != sizeof(nt_hash->hash)) {
654 0 : TALLOC_FREE(nt_hash);
655 0 : return NULL;
656 : }
657 : } else {
658 28168 : E_md4hash(password, nt_hash->hash);
659 : }
660 :
661 28168 : cred->nt_hash = nt_hash;
662 28168 : nt_hash = NULL;
663 :
664 42401 : return_hash:
665 42401 : nt_hash = talloc(mem_ctx, struct samr_Password);
666 42401 : if (nt_hash == NULL) {
667 0 : return NULL;
668 : }
669 :
670 42401 : *nt_hash = *cred->nt_hash;
671 :
672 42401 : return nt_hash;
673 : }
674 :
675 : /**
676 : * Obtain the old password, in the form MD4(unicode(password)) for this credentials context.
677 : *
678 : * Sometimes we only have this much of the password, while the rest of
679 : * the time this call avoids calling E_md4hash themselves.
680 : *
681 : * @param cred credentials context
682 : * @retval If set, the cleartext password, otherwise NULL
683 : */
684 360 : _PUBLIC_ struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
685 : TALLOC_CTX *mem_ctx)
686 : {
687 360 : const char *old_password = NULL;
688 :
689 360 : if (cred->old_nt_hash != NULL) {
690 0 : struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
691 0 : if (!nt_hash) {
692 0 : return NULL;
693 : }
694 :
695 0 : *nt_hash = *cred->old_nt_hash;
696 :
697 0 : return nt_hash;
698 : }
699 :
700 360 : old_password = cli_credentials_get_old_password(cred);
701 360 : if (old_password) {
702 219 : struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
703 219 : if (!nt_hash) {
704 0 : return NULL;
705 : }
706 :
707 219 : E_md4hash(old_password, nt_hash->hash);
708 :
709 219 : return nt_hash;
710 : }
711 :
712 141 : return NULL;
713 : }
714 :
715 : /**
716 : * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
717 : * @param cred credentials context
718 : * @retval The domain set on this context.
719 : * @note Return value will never be NULL except by programmer error.
720 : */
721 758508 : _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred)
722 : {
723 758508 : if (cred->machine_account_pending) {
724 0 : cli_credentials_set_machine_account(cred,
725 : cred->machine_account_pending_lp_ctx);
726 : }
727 :
728 758508 : if (cred->domain_obtained == CRED_CALLBACK &&
729 0 : !cred->callback_running) {
730 0 : cred->callback_running = true;
731 0 : cred->domain = cred->domain_cb(cred);
732 0 : cred->callback_running = false;
733 0 : if (cred->domain_obtained == CRED_CALLBACK) {
734 0 : cred->domain_obtained = CRED_CALLBACK_RESULT;
735 0 : cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
736 : }
737 : }
738 :
739 758508 : return cred->domain;
740 : }
741 :
742 : /**
743 : * @brief Obtain the domain for this credential context.
744 : *
745 : * @param[in] cred The credential context.
746 : *
747 : * @param[out] obtained A pointer to store the obtained information.
748 : *
749 : * @return The domain name or NULL if an error occurred.
750 : */
751 87 : _PUBLIC_ const char *cli_credentials_get_domain_and_obtained(
752 : struct cli_credentials *cred,
753 : enum credentials_obtained *obtained)
754 : {
755 87 : const char *domain = cli_credentials_get_domain(cred);
756 :
757 87 : if (obtained != NULL) {
758 87 : *obtained = cred->domain_obtained;
759 : }
760 :
761 87 : return domain;
762 : }
763 :
764 :
765 576776 : _PUBLIC_ bool cli_credentials_set_domain(struct cli_credentials *cred,
766 : const char *val,
767 : enum credentials_obtained obtained)
768 : {
769 576776 : if (obtained >= cred->domain_obtained) {
770 : /* it is important that the domain be in upper case,
771 : * particularly for the sensitive NTLMv2
772 : * calculations */
773 515014 : cred->domain = strupper_talloc(cred, val);
774 515014 : cred->domain_obtained = obtained;
775 : /* setting domain does not mean we have to invalidate ccache
776 : * because domain in not used for Kerberos operations.
777 : * If ccache invalidation is required, one will anyway specify
778 : * a password to kinit, and that will force invalidation of the ccache
779 : */
780 515014 : return true;
781 : }
782 :
783 61762 : return false;
784 : }
785 :
786 0 : bool cli_credentials_set_domain_callback(struct cli_credentials *cred,
787 : const char *(*domain_cb) (struct cli_credentials *))
788 : {
789 0 : if (cred->domain_obtained < CRED_CALLBACK) {
790 0 : cred->domain_cb = domain_cb;
791 0 : cred->domain_obtained = CRED_CALLBACK;
792 0 : return true;
793 : }
794 :
795 0 : return false;
796 : }
797 :
798 : /**
799 : * Obtain the Kerberos realm for this credentials context.
800 : * @param cred credentials context
801 : * @retval The realm set on this context.
802 : * @note Return value will never be NULL except by programmer error.
803 : */
804 825772 : _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred)
805 : {
806 825772 : if (cred->machine_account_pending) {
807 0 : cli_credentials_set_machine_account(cred,
808 : cred->machine_account_pending_lp_ctx);
809 : }
810 :
811 825772 : if (cred->realm_obtained == CRED_CALLBACK &&
812 0 : !cred->callback_running) {
813 0 : cred->callback_running = true;
814 0 : cred->realm = cred->realm_cb(cred);
815 0 : cred->callback_running = false;
816 0 : if (cred->realm_obtained == CRED_CALLBACK) {
817 0 : cred->realm_obtained = CRED_CALLBACK_RESULT;
818 0 : cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
819 : }
820 : }
821 :
822 825772 : return cred->realm;
823 : }
824 :
825 : /**
826 : * Set the realm for this credentials context, and force it to
827 : * uppercase for the sanity of our local kerberos libraries
828 : */
829 458455 : _PUBLIC_ bool cli_credentials_set_realm(struct cli_credentials *cred,
830 : const char *val,
831 : enum credentials_obtained obtained)
832 : {
833 458455 : if (obtained >= cred->realm_obtained) {
834 451451 : cred->realm = strupper_talloc(cred, val);
835 451451 : cred->realm_obtained = obtained;
836 451451 : cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
837 451451 : return true;
838 : }
839 :
840 7004 : return false;
841 : }
842 :
843 0 : bool cli_credentials_set_realm_callback(struct cli_credentials *cred,
844 : const char *(*realm_cb) (struct cli_credentials *))
845 : {
846 0 : if (cred->realm_obtained < CRED_CALLBACK) {
847 0 : cred->realm_cb = realm_cb;
848 0 : cred->realm_obtained = CRED_CALLBACK;
849 0 : return true;
850 : }
851 :
852 0 : return false;
853 : }
854 :
855 : /**
856 : * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context.
857 : *
858 : * @param cred credentials context
859 : * @retval The workstation name set on this context.
860 : * @note Return value will never be NULL except by programmer error.
861 : */
862 124452 : _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cred)
863 : {
864 124452 : if (cred->workstation_obtained == CRED_CALLBACK &&
865 0 : !cred->callback_running) {
866 0 : cred->callback_running = true;
867 0 : cred->workstation = cred->workstation_cb(cred);
868 0 : cred->callback_running = false;
869 0 : if (cred->workstation_obtained == CRED_CALLBACK) {
870 0 : cred->workstation_obtained = CRED_CALLBACK_RESULT;
871 : }
872 : }
873 :
874 124452 : return cred->workstation;
875 : }
876 :
877 461318 : _PUBLIC_ bool cli_credentials_set_workstation(struct cli_credentials *cred,
878 : const char *val,
879 : enum credentials_obtained obtained)
880 : {
881 461318 : if (obtained >= cred->workstation_obtained) {
882 419441 : cred->workstation = talloc_strdup(cred, val);
883 419441 : cred->workstation_obtained = obtained;
884 419441 : return true;
885 : }
886 :
887 41457 : return false;
888 : }
889 :
890 0 : bool cli_credentials_set_workstation_callback(struct cli_credentials *cred,
891 : const char *(*workstation_cb) (struct cli_credentials *))
892 : {
893 0 : if (cred->workstation_obtained < CRED_CALLBACK) {
894 0 : cred->workstation_cb = workstation_cb;
895 0 : cred->workstation_obtained = CRED_CALLBACK;
896 0 : return true;
897 : }
898 :
899 0 : return false;
900 : }
901 :
902 : /**
903 : * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields
904 : *
905 : * The format accepted is [domain\\]user[%password] or user[@realm][%password]
906 : *
907 : * @param credentials Credentials structure on which to set the password
908 : * @param data the string containing the username, password etc
909 : * @param obtained This enum describes how 'specified' this password is
910 : */
911 :
912 242531 : _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
913 : {
914 1026 : char *uname, *p;
915 242531 : char *uname_free = NULL;
916 :
917 242531 : if (strcmp("%",data) == 0) {
918 452 : cli_credentials_set_anonymous(credentials);
919 452 : return;
920 : }
921 :
922 242079 : uname = talloc_strdup(credentials, data);
923 242079 : uname_free = uname;
924 :
925 242079 : if ((p = strchr_m(uname,'%'))) {
926 23267 : *p = 0;
927 23267 : cli_credentials_set_password(credentials, p+1, obtained);
928 : }
929 :
930 242079 : if ((p = strchr_m(uname,'@'))) {
931 : /*
932 : * We also need to set username and domain
933 : * in order to undo the effect of
934 : * cli_credentials_guess().
935 : */
936 379 : cli_credentials_set_username(credentials, uname, obtained);
937 379 : cli_credentials_set_domain(credentials, "", obtained);
938 :
939 379 : cli_credentials_set_principal(credentials, uname, obtained);
940 379 : *p = 0;
941 379 : cli_credentials_set_realm(credentials, p+1, obtained);
942 379 : TALLOC_FREE(uname_free);
943 379 : return;
944 241700 : } else if ((p = strchr_m(uname,'\\'))
945 241085 : || (p = strchr_m(uname, '/'))
946 239754 : || (p = strchr_m(uname, credentials->winbind_separator)))
947 : {
948 1974 : const char *domain = NULL;
949 :
950 1974 : domain = uname;
951 1974 : *p = 0;
952 1974 : uname = p+1;
953 :
954 1980 : if (obtained == credentials->realm_obtained &&
955 6 : !strequal_m(credentials->domain, domain))
956 : {
957 : /*
958 : * We need to undo a former set with the same level
959 : * in order to get the expected result from
960 : * cli_credentials_get_principal().
961 : *
962 : * But we only need to do that if the domain
963 : * actually changes.
964 : */
965 5 : cli_credentials_set_realm(credentials, domain, obtained);
966 : }
967 1974 : cli_credentials_set_domain(credentials, domain, obtained);
968 : }
969 241702 : if (obtained == credentials->principal_obtained &&
970 8 : !strequal_m(credentials->username, uname))
971 : {
972 : /*
973 : * We need to undo a former set with the same level
974 : * in order to get the expected result from
975 : * cli_credentials_get_principal().
976 : *
977 : * But we only need to do that if the username
978 : * actually changes.
979 : */
980 2 : credentials->principal_obtained = CRED_UNINITIALISED;
981 2 : credentials->principal = NULL;
982 : }
983 241700 : cli_credentials_set_username(credentials, uname, obtained);
984 :
985 241700 : TALLOC_FREE(uname_free);
986 : }
987 :
988 : /**
989 : * Given a a credentials structure, print it as a string
990 : *
991 : * The format output is [domain\\]user[%password] or user[@realm][%password]
992 : *
993 : * @param credentials Credentials structure on which to set the password
994 : * @param mem_ctx The memory context to place the result on
995 : */
996 :
997 514 : _PUBLIC_ char *cli_credentials_get_unparsed_name(struct cli_credentials *credentials, TALLOC_CTX *mem_ctx)
998 : {
999 514 : const char *bind_dn = cli_credentials_get_bind_dn(credentials);
1000 514 : const char *domain = NULL;
1001 514 : const char *username = NULL;
1002 514 : char *name = NULL;
1003 :
1004 514 : if (bind_dn) {
1005 0 : name = talloc_strdup(mem_ctx, bind_dn);
1006 : } else {
1007 514 : cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain);
1008 514 : if (domain && domain[0]) {
1009 410 : name = talloc_asprintf(mem_ctx, "%s\\%s",
1010 : domain, username);
1011 : } else {
1012 104 : name = talloc_asprintf(mem_ctx, "%s",
1013 : username);
1014 : }
1015 : }
1016 514 : return name;
1017 : }
1018 :
1019 :
1020 : /**
1021 : * Specifies default values for domain, workstation and realm
1022 : * from the smb.conf configuration file
1023 : *
1024 : * @param cred Credentials structure to fill in
1025 : *
1026 : * @return true on success, false on error.
1027 : */
1028 276667 : _PUBLIC_ bool cli_credentials_set_conf(struct cli_credentials *cred,
1029 : struct loadparm_context *lp_ctx)
1030 : {
1031 276667 : const char *sep = NULL;
1032 276667 : const char *realm = lpcfg_realm(lp_ctx);
1033 3895 : enum credentials_client_protection protection =
1034 276667 : lpcfg_client_protection(lp_ctx);
1035 276667 : const char *workgroup = lpcfg_workgroup(lp_ctx);
1036 276667 : const char *netbios_name = lpcfg_netbios_name(lp_ctx);
1037 3895 : bool ok;
1038 :
1039 276667 : (void)cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
1040 :
1041 276667 : if (workgroup != NULL && strlen(workgroup) == 0) {
1042 0 : workgroup = NULL;
1043 : }
1044 :
1045 276667 : if (workgroup != NULL) {
1046 276667 : if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) {
1047 1500 : ok = cli_credentials_set_domain(cred,
1048 : workgroup,
1049 : CRED_SPECIFIED);
1050 1500 : if (!ok) {
1051 0 : DBG_ERR("Failed to set domain!\n");
1052 0 : return false;
1053 : }
1054 : } else {
1055 275167 : (void)cli_credentials_set_domain(cred,
1056 : workgroup,
1057 : CRED_SMB_CONF);
1058 : }
1059 : }
1060 :
1061 276667 : if (netbios_name != NULL && strlen(netbios_name) == 0) {
1062 0 : netbios_name = NULL;
1063 : }
1064 :
1065 276667 : if (netbios_name != NULL) {
1066 276667 : if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) {
1067 285 : ok = cli_credentials_set_workstation(cred,
1068 : netbios_name,
1069 : CRED_SPECIFIED);
1070 285 : if (!ok) {
1071 0 : DBG_ERR("Failed to set workstation!\n");
1072 0 : return false;
1073 : }
1074 : } else {
1075 276382 : (void)cli_credentials_set_workstation(cred,
1076 : netbios_name,
1077 : CRED_SMB_CONF);
1078 : }
1079 : }
1080 :
1081 276667 : if (realm != NULL && strlen(realm) == 0) {
1082 115171 : realm = NULL;
1083 : }
1084 :
1085 276103 : if (realm != NULL) {
1086 160932 : if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) {
1087 248 : ok = cli_credentials_set_realm(cred,
1088 : realm,
1089 : CRED_SPECIFIED);
1090 248 : if (!ok) {
1091 0 : DBG_ERR("Failed to set realm!\n");
1092 0 : return false;
1093 : }
1094 : } else {
1095 160684 : (void)cli_credentials_set_realm(cred,
1096 : realm,
1097 : CRED_SMB_CONF);
1098 : }
1099 : }
1100 :
1101 276667 : sep = lpcfg_winbind_separator(lp_ctx);
1102 276667 : if (sep != NULL && sep[0] != '\0') {
1103 276667 : cred->winbind_separator = *lpcfg_winbind_separator(lp_ctx);
1104 : }
1105 :
1106 276667 : if (cred->signing_state_obtained <= CRED_SMB_CONF) {
1107 : /* Will be set to default for invalid smb.conf values */
1108 275567 : cred->signing_state = lpcfg_client_signing(lp_ctx);
1109 275567 : if (cred->signing_state == SMB_SIGNING_DEFAULT) {
1110 275553 : switch (protection) {
1111 271667 : case CRED_CLIENT_PROTECTION_DEFAULT:
1112 271667 : break;
1113 0 : case CRED_CLIENT_PROTECTION_PLAIN:
1114 0 : cred->signing_state = SMB_SIGNING_OFF;
1115 0 : break;
1116 0 : case CRED_CLIENT_PROTECTION_SIGN:
1117 : case CRED_CLIENT_PROTECTION_ENCRYPT:
1118 0 : cred->signing_state = SMB_SIGNING_REQUIRED;
1119 0 : break;
1120 : }
1121 : }
1122 :
1123 275567 : cred->signing_state_obtained = CRED_SMB_CONF;
1124 : }
1125 :
1126 276667 : if (cred->ipc_signing_state_obtained <= CRED_SMB_CONF) {
1127 : /* Will be set to required for invalid smb.conf values */
1128 276666 : cred->ipc_signing_state = lpcfg_client_ipc_signing(lp_ctx);
1129 276666 : cred->ipc_signing_state_obtained = CRED_SMB_CONF;
1130 : }
1131 :
1132 276667 : if (cred->encryption_state_obtained <= CRED_SMB_CONF) {
1133 : /* Will be set to default for invalid smb.conf values */
1134 275567 : cred->encryption_state = lpcfg_client_smb_encrypt(lp_ctx);
1135 275567 : if (cred->encryption_state == SMB_ENCRYPTION_DEFAULT) {
1136 275471 : switch (protection) {
1137 271585 : case CRED_CLIENT_PROTECTION_DEFAULT:
1138 271585 : break;
1139 0 : case CRED_CLIENT_PROTECTION_PLAIN:
1140 : case CRED_CLIENT_PROTECTION_SIGN:
1141 0 : cred->encryption_state = SMB_ENCRYPTION_OFF;
1142 0 : break;
1143 0 : case CRED_CLIENT_PROTECTION_ENCRYPT:
1144 0 : cred->encryption_state = SMB_ENCRYPTION_REQUIRED;
1145 0 : break;
1146 : }
1147 : }
1148 : }
1149 :
1150 276667 : if (cred->kerberos_state_obtained <= CRED_SMB_CONF) {
1151 : /* Will be set to default for invalid smb.conf values */
1152 213867 : cred->kerberos_state = lpcfg_client_use_kerberos(lp_ctx);
1153 213867 : cred->kerberos_state_obtained = CRED_SMB_CONF;
1154 : }
1155 :
1156 276667 : if (cred->gensec_features_obtained <= CRED_SMB_CONF) {
1157 275520 : switch (protection) {
1158 271633 : case CRED_CLIENT_PROTECTION_DEFAULT:
1159 271633 : break;
1160 0 : case CRED_CLIENT_PROTECTION_PLAIN:
1161 0 : cred->gensec_features = 0;
1162 0 : break;
1163 0 : case CRED_CLIENT_PROTECTION_SIGN:
1164 0 : cred->gensec_features = GENSEC_FEATURE_SIGN;
1165 0 : break;
1166 0 : case CRED_CLIENT_PROTECTION_ENCRYPT:
1167 0 : cred->gensec_features =
1168 : GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL;
1169 0 : break;
1170 : }
1171 275520 : cred->gensec_features_obtained = CRED_SMB_CONF;
1172 : }
1173 :
1174 272772 : return true;
1175 : }
1176 :
1177 : /**
1178 : * Guess defaults for credentials from environment variables,
1179 : * and from the configuration file
1180 : *
1181 : * @param cred Credentials structure to fill in
1182 : */
1183 100785 : _PUBLIC_ bool cli_credentials_guess(struct cli_credentials *cred,
1184 : struct loadparm_context *lp_ctx)
1185 : {
1186 443 : const char *error_string;
1187 100785 : const char *env = NULL;
1188 100785 : struct passwd *pwd = NULL;
1189 443 : bool ok;
1190 :
1191 100785 : if (lp_ctx != NULL) {
1192 100783 : ok = cli_credentials_set_conf(cred, lp_ctx);
1193 100783 : if (!ok) {
1194 0 : return false;
1195 : }
1196 : }
1197 :
1198 100785 : pwd = getpwuid(getuid());
1199 100785 : if (pwd != NULL) {
1200 100218 : size_t len = strlen(pwd->pw_name);
1201 :
1202 100218 : if (len > 0 && len <= 1024) {
1203 100218 : (void)cli_credentials_parse_string(cred,
1204 99775 : pwd->pw_name,
1205 : CRED_GUESS_ENV);
1206 : }
1207 : }
1208 :
1209 100785 : env = getenv("LOGNAME");
1210 100785 : if (env != NULL) {
1211 0 : size_t len = strlen(env);
1212 :
1213 0 : if (len > 0 && len <= 1024) {
1214 0 : (void)cli_credentials_set_username(cred,
1215 : env,
1216 : CRED_GUESS_ENV);
1217 : }
1218 : }
1219 :
1220 100785 : env = getenv("USER");
1221 100785 : if (env != NULL) {
1222 100785 : size_t len = strlen(env);
1223 :
1224 100785 : if (len > 0 && len <= 1024) {
1225 100785 : char *p = NULL;
1226 :
1227 100785 : (void)cli_credentials_parse_string(cred,
1228 : env,
1229 : CRED_GUESS_ENV);
1230 100785 : if ((p = strchr_m(env, '%'))) {
1231 0 : memset(p, '\0', strlen(cred->password));
1232 : }
1233 : }
1234 : }
1235 :
1236 100785 : env = getenv("PASSWD");
1237 100785 : if (env != NULL) {
1238 6 : size_t len = strlen(env);
1239 :
1240 6 : if (len > 0 && len <= 1024) {
1241 6 : (void)cli_credentials_set_password(cred,
1242 : env,
1243 : CRED_GUESS_ENV);
1244 : }
1245 : }
1246 :
1247 100785 : env = getenv("PASSWD_FD");
1248 100785 : if (env != NULL) {
1249 2 : size_t len = strlen(env);
1250 :
1251 2 : if (len > 0 && len <= 1024) {
1252 2 : int fd = atoi(env);
1253 :
1254 2 : (void)cli_credentials_parse_password_fd(cred,
1255 : fd,
1256 : CRED_GUESS_FILE);
1257 : }
1258 : }
1259 :
1260 100785 : env = getenv("PASSWD_FILE");
1261 100785 : if (env != NULL) {
1262 2 : size_t len = strlen(env);
1263 :
1264 2 : if (len > 0 && len <= 4096) {
1265 2 : (void)cli_credentials_parse_password_file(cred,
1266 : env,
1267 : CRED_GUESS_FILE);
1268 : }
1269 : }
1270 :
1271 201568 : if (lp_ctx != NULL &&
1272 100783 : cli_credentials_get_kerberos_state(cred) != CRED_USE_KERBEROS_DISABLED) {
1273 99359 : (void)cli_credentials_set_ccache(cred,
1274 : lp_ctx,
1275 : NULL,
1276 : CRED_GUESS_FILE,
1277 : &error_string);
1278 : }
1279 :
1280 100342 : return true;
1281 : }
1282 :
1283 : /**
1284 : * Attach NETLOGON credentials for use with SCHANNEL
1285 : */
1286 :
1287 1729 : _PUBLIC_ void cli_credentials_set_netlogon_creds(
1288 : struct cli_credentials *cred,
1289 : const struct netlogon_creds_CredentialState *netlogon_creds)
1290 : {
1291 1729 : TALLOC_FREE(cred->netlogon_creds);
1292 1729 : if (netlogon_creds == NULL) {
1293 549 : return;
1294 : }
1295 1140 : cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds);
1296 : }
1297 :
1298 : /**
1299 : * Return attached NETLOGON credentials
1300 : */
1301 :
1302 573782 : _PUBLIC_ struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
1303 : {
1304 573782 : return cred->netlogon_creds;
1305 : }
1306 :
1307 : /**
1308 : * Set NETLOGON secure channel type
1309 : */
1310 :
1311 71650 : _PUBLIC_ void cli_credentials_set_secure_channel_type(struct cli_credentials *cred,
1312 : enum netr_SchannelType secure_channel_type)
1313 : {
1314 71650 : cred->secure_channel_type = secure_channel_type;
1315 71650 : }
1316 :
1317 : /**
1318 : * Return NETLOGON secure channel type
1319 : */
1320 :
1321 134818 : _PUBLIC_ time_t cli_credentials_get_password_last_changed_time(struct cli_credentials *cred)
1322 : {
1323 134818 : return cred->password_last_changed_time;
1324 : }
1325 :
1326 : /**
1327 : * Set NETLOGON secure channel type
1328 : */
1329 :
1330 67668 : _PUBLIC_ void cli_credentials_set_password_last_changed_time(struct cli_credentials *cred,
1331 : time_t last_changed_time)
1332 : {
1333 67668 : cred->password_last_changed_time = last_changed_time;
1334 67668 : }
1335 :
1336 : /**
1337 : * Return NETLOGON secure channel type
1338 : */
1339 :
1340 10779 : _PUBLIC_ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred)
1341 : {
1342 10779 : return cred->secure_channel_type;
1343 : }
1344 :
1345 : /**
1346 : * Fill in a credentials structure as the anonymous user
1347 : */
1348 163863 : _PUBLIC_ void cli_credentials_set_anonymous(struct cli_credentials *cred)
1349 : {
1350 163863 : cli_credentials_set_username(cred, "", CRED_SPECIFIED);
1351 163863 : cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
1352 163863 : cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
1353 163863 : cli_credentials_set_principal(cred, NULL, CRED_SPECIFIED);
1354 163863 : cli_credentials_set_realm(cred, NULL, CRED_SPECIFIED);
1355 163863 : cli_credentials_set_workstation(cred, "", CRED_UNINITIALISED);
1356 163863 : cli_credentials_set_kerberos_state(cred,
1357 : CRED_USE_KERBEROS_DISABLED,
1358 : CRED_SPECIFIED);
1359 163863 : }
1360 :
1361 : /**
1362 : * Describe a credentials context as anonymous or authenticated
1363 : * @retval true if anonymous, false if a username is specified
1364 : */
1365 :
1366 185774 : _PUBLIC_ bool cli_credentials_is_anonymous(struct cli_credentials *cred)
1367 : {
1368 2618 : const char *username;
1369 :
1370 : /* if bind dn is set it's not anonymous */
1371 185774 : if (cred->bind_dn) {
1372 0 : return false;
1373 : }
1374 :
1375 185774 : if (cred->machine_account_pending) {
1376 14 : cli_credentials_set_machine_account(cred,
1377 : cred->machine_account_pending_lp_ctx);
1378 : }
1379 :
1380 : /* if principal is set, it's not anonymous */
1381 185774 : if ((cred->principal != NULL) && cred->principal_obtained >= cred->username_obtained) {
1382 37405 : return false;
1383 : }
1384 :
1385 147174 : username = cli_credentials_get_username(cred);
1386 :
1387 : /* Yes, it is deliberate that we die if we have a NULL pointer
1388 : * here - anonymous is "", not NULL, which is 'never specified,
1389 : * never guessed', ie programmer bug */
1390 147174 : if (!username[0]) {
1391 9628 : return true;
1392 : }
1393 :
1394 136269 : return false;
1395 : }
1396 :
1397 : /**
1398 : * Mark the current password for a credentials struct as wrong. This will
1399 : * cause the password to be prompted again (if a callback is set).
1400 : *
1401 : * This will decrement the number of times the password can be tried.
1402 : *
1403 : * @retval whether the credentials struct is finished
1404 : */
1405 1634 : _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred)
1406 : {
1407 1634 : if (cred->password_obtained != CRED_CALLBACK_RESULT) {
1408 1627 : return false;
1409 : }
1410 :
1411 0 : if (cred->password_tries == 0) {
1412 0 : return false;
1413 : }
1414 :
1415 0 : cred->password_tries--;
1416 :
1417 0 : if (cred->password_tries == 0) {
1418 0 : return false;
1419 : }
1420 :
1421 0 : cred->password_obtained = CRED_CALLBACK;
1422 0 : return true;
1423 : }
1424 :
1425 82007 : _PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx,
1426 : const char **username,
1427 : const char **domain)
1428 : {
1429 82007 : if (cred->principal_obtained >= cred->username_obtained) {
1430 4026 : *domain = talloc_strdup(mem_ctx, "");
1431 4026 : *username = cli_credentials_get_principal(cred, mem_ctx);
1432 : } else {
1433 77981 : *domain = cli_credentials_get_domain(cred);
1434 77981 : *username = cli_credentials_get_username(cred);
1435 : }
1436 82007 : }
1437 :
1438 : /**
1439 : * Read a named file, and parse it for username, domain, realm and password
1440 : *
1441 : * @param credentials Credentials structure on which to set the password
1442 : * @param file a named file to read the details from
1443 : * @param obtained This enum describes how 'specified' this password is
1444 : */
1445 :
1446 61 : _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained)
1447 : {
1448 61 : uint16_t len = 0;
1449 7 : char *ptr, *val, *param;
1450 7 : char **lines;
1451 7 : int i, numlines;
1452 61 : const char *realm = NULL;
1453 61 : const char *domain = NULL;
1454 61 : const char *password = NULL;
1455 61 : const char *username = NULL;
1456 :
1457 61 : lines = file_lines_load(file, &numlines, 0, NULL);
1458 :
1459 61 : if (lines == NULL)
1460 : {
1461 : /* fail if we can't open the credentials file */
1462 0 : d_printf("ERROR: Unable to open credentials file!\n");
1463 0 : return false;
1464 : }
1465 :
1466 249 : for (i = 0; i < numlines; i++) {
1467 188 : len = strlen(lines[i]);
1468 :
1469 188 : if (len == 0)
1470 0 : continue;
1471 :
1472 : /* break up the line into parameter & value.
1473 : * will need to eat a little whitespace possibly */
1474 188 : param = lines[i];
1475 188 : if (!(ptr = strchr_m (lines[i], '=')))
1476 0 : continue;
1477 :
1478 188 : val = ptr+1;
1479 188 : *ptr = '\0';
1480 :
1481 : /* eat leading white space */
1482 192 : while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
1483 4 : val++;
1484 :
1485 188 : if (strwicmp("password", param) == 0) {
1486 54 : password = val;
1487 127 : } else if (strwicmp("username", param) == 0) {
1488 54 : username = val;
1489 66 : } else if (strwicmp("domain", param) == 0) {
1490 52 : domain = val;
1491 7 : } else if (strwicmp("realm", param) == 0) {
1492 7 : realm = val;
1493 : }
1494 :
1495 : /*
1496 : * We need to readd '=' in order to let
1497 : * the strlen() work in the last loop
1498 : * that clears the memory.
1499 : */
1500 188 : *ptr = '=';
1501 : }
1502 :
1503 61 : if (realm != NULL && strlen(realm) != 0) {
1504 : /*
1505 : * only overwrite with a valid string
1506 : */
1507 7 : cli_credentials_set_realm(cred, realm, obtained);
1508 : }
1509 :
1510 61 : if (domain != NULL && strlen(domain) != 0) {
1511 : /*
1512 : * only overwrite with a valid string
1513 : */
1514 59 : cli_credentials_set_domain(cred, domain, obtained);
1515 : }
1516 :
1517 61 : if (password != NULL) {
1518 : /*
1519 : * Here we allow "".
1520 : */
1521 61 : cli_credentials_set_password(cred, password, obtained);
1522 : }
1523 :
1524 61 : if (username != NULL) {
1525 : /*
1526 : * The last "username" line takes preference
1527 : * if the string also contains domain, realm or
1528 : * password.
1529 : */
1530 61 : cli_credentials_parse_string(cred, username, obtained);
1531 : }
1532 :
1533 249 : for (i = 0; i < numlines; i++) {
1534 188 : len = strlen(lines[i]);
1535 188 : memset(lines[i], 0, len);
1536 : }
1537 61 : talloc_free(lines);
1538 :
1539 61 : return true;
1540 : }
1541 :
1542 : /**
1543 : * Read a named file, and parse it for a password
1544 : *
1545 : * @param credentials Credentials structure on which to set the password
1546 : * @param file a named file to read the password from
1547 : * @param obtained This enum describes how 'specified' this password is
1548 : */
1549 :
1550 2 : _PUBLIC_ bool cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
1551 : {
1552 2 : int fd = open(file, O_RDONLY, 0);
1553 0 : bool ret;
1554 :
1555 2 : if (fd < 0) {
1556 0 : fprintf(stderr, "Error opening password file %s: %s\n",
1557 0 : file, strerror(errno));
1558 0 : return false;
1559 : }
1560 :
1561 2 : ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
1562 :
1563 2 : close(fd);
1564 :
1565 2 : return ret;
1566 : }
1567 :
1568 :
1569 : /**
1570 : * Read a file descriptor, and parse it for a password (eg from a file or stdin)
1571 : *
1572 : * @param credentials Credentials structure on which to set the password
1573 : * @param fd open file descriptor to read the password from
1574 : * @param obtained This enum describes how 'specified' this password is
1575 : */
1576 :
1577 4 : _PUBLIC_ bool cli_credentials_parse_password_fd(struct cli_credentials *credentials,
1578 : int fd, enum credentials_obtained obtained)
1579 : {
1580 0 : char *p;
1581 0 : char pass[128];
1582 :
1583 4 : if (credentials->password_obtained >= obtained) {
1584 0 : return false;
1585 : }
1586 :
1587 4 : for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
1588 50 : p && p - pass < sizeof(pass) - 1;) {
1589 46 : switch (read(fd, p, 1)) {
1590 46 : case 1:
1591 46 : if (*p != '\n' && *p != '\0') {
1592 42 : *++p = '\0'; /* advance p, and null-terminate pass */
1593 42 : break;
1594 : }
1595 :
1596 0 : FALL_THROUGH;
1597 : case 0:
1598 4 : if (p - pass) {
1599 4 : *p = '\0'; /* null-terminate it, just in case... */
1600 4 : p = NULL; /* then force the loop condition to become false */
1601 4 : break;
1602 : }
1603 :
1604 0 : fprintf(stderr,
1605 : "Error reading password from file descriptor "
1606 : "%d: empty password\n",
1607 : fd);
1608 0 : return false;
1609 :
1610 0 : default:
1611 0 : fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
1612 0 : fd, strerror(errno));
1613 0 : return false;
1614 : }
1615 : }
1616 :
1617 4 : cli_credentials_set_password(credentials, pass, obtained);
1618 4 : return true;
1619 : }
1620 :
1621 : /**
1622 : * @brief Set the SMB signing state to request for a SMB connection.
1623 : *
1624 : * @param[in] creds The credentials structure to update.
1625 : *
1626 : * @param[in] signing_state The signing state to set.
1627 : *
1628 : * @param obtained This way the described signing state was specified.
1629 : *
1630 : * @return true if we could set the signing state, false otherwise.
1631 : */
1632 3537 : _PUBLIC_ bool cli_credentials_set_smb_signing(struct cli_credentials *creds,
1633 : enum smb_signing_setting signing_state,
1634 : enum credentials_obtained obtained)
1635 : {
1636 3537 : if (obtained >= creds->signing_state_obtained) {
1637 3537 : creds->signing_state_obtained = obtained;
1638 3537 : creds->signing_state = signing_state;
1639 3537 : return true;
1640 : }
1641 :
1642 0 : return false;
1643 : }
1644 :
1645 : /**
1646 : * @brief Obtain the SMB signing state from a credentials structure.
1647 : *
1648 : * @param[in] creds The credential structure to obtain the SMB signing state
1649 : * from.
1650 : *
1651 : * @return The SMB signing state.
1652 : */
1653 : _PUBLIC_ enum smb_signing_setting
1654 17409 : cli_credentials_get_smb_signing(struct cli_credentials *creds)
1655 : {
1656 17409 : return creds->signing_state;
1657 : }
1658 :
1659 : /**
1660 : * @brief Set the SMB IPC signing state to request for a SMB connection.
1661 : *
1662 : * @param[in] creds The credentials structure to update.
1663 : *
1664 : * @param[in] signing_state The signing state to set.
1665 : *
1666 : * @param obtained This way the described signing state was specified.
1667 : *
1668 : * @return true if we could set the signing state, false otherwise.
1669 : */
1670 : _PUBLIC_ bool
1671 80 : cli_credentials_set_smb_ipc_signing(struct cli_credentials *creds,
1672 : enum smb_signing_setting ipc_signing_state,
1673 : enum credentials_obtained obtained)
1674 : {
1675 80 : if (obtained >= creds->ipc_signing_state_obtained) {
1676 80 : creds->ipc_signing_state_obtained = obtained;
1677 80 : creds->ipc_signing_state = ipc_signing_state;
1678 80 : return true;
1679 : }
1680 :
1681 0 : return false;
1682 : }
1683 :
1684 : /**
1685 : * @brief Obtain the SMB IPC signing state from a credentials structure.
1686 : *
1687 : * @param[in] creds The credential structure to obtain the SMB IPC signing
1688 : * state from.
1689 : *
1690 : * @return The SMB signing state.
1691 : */
1692 : _PUBLIC_ enum smb_signing_setting
1693 1627 : cli_credentials_get_smb_ipc_signing(struct cli_credentials *creds)
1694 : {
1695 1627 : return creds->ipc_signing_state;
1696 : }
1697 :
1698 : /**
1699 : * @brief Set the SMB encryption state to request for a SMB connection.
1700 : *
1701 : * @param[in] creds The credentials structure to update.
1702 : *
1703 : * @param[in] encryption_state The encryption state to set.
1704 : *
1705 : * @param obtained This way the described encryption state was specified.
1706 : *
1707 : * @return true if we could set the encryption state, false otherwise.
1708 : */
1709 1521 : _PUBLIC_ bool cli_credentials_set_smb_encryption(struct cli_credentials *creds,
1710 : enum smb_encryption_setting encryption_state,
1711 : enum credentials_obtained obtained)
1712 : {
1713 1521 : if (obtained >= creds->encryption_state_obtained) {
1714 1521 : creds->encryption_state_obtained = obtained;
1715 1521 : creds->encryption_state = encryption_state;
1716 1521 : return true;
1717 : }
1718 :
1719 0 : return false;
1720 : }
1721 :
1722 14 : static const char *obtained_to_str(enum credentials_obtained obtained)
1723 : {
1724 14 : switch (obtained) {
1725 0 : case CRED_UNINITIALISED:
1726 0 : return "CRED_UNINITIALISED";
1727 0 : case CRED_SMB_CONF:
1728 0 : return "CRED_SMB_CONF";
1729 0 : case CRED_CALLBACK:
1730 0 : return "CRED_CALLBACK";
1731 0 : case CRED_GUESS_ENV:
1732 0 : return "CRED_GUESS_ENV";
1733 0 : case CRED_GUESS_FILE:
1734 0 : return "CRED_GUESS_FILE";
1735 0 : case CRED_CALLBACK_RESULT:
1736 0 : return "CRED_CALLBACK_RESULT";
1737 3 : case CRED_SPECIFIED:
1738 3 : return "CRED_SPECIFIED";
1739 : }
1740 :
1741 : /* Never reached */
1742 0 : return "";
1743 : }
1744 :
1745 1 : static const char *krb5_state_to_str(enum credentials_use_kerberos krb5_state)
1746 : {
1747 1 : switch (krb5_state) {
1748 0 : case CRED_USE_KERBEROS_DISABLED:
1749 0 : return "CRED_USE_KERBEROS_DISABLED";
1750 1 : case CRED_USE_KERBEROS_DESIRED:
1751 1 : return "CRED_USE_KERBEROS_DESIRED";
1752 0 : case CRED_USE_KERBEROS_REQUIRED:
1753 0 : return "CRED_USE_KERBEROS_REQUIRED";
1754 : }
1755 :
1756 : /* Never reached */
1757 0 : return "";
1758 : }
1759 :
1760 1 : static const char *krb5_fwd_to_str(enum credentials_krb_forwardable krb5_fwd)
1761 : {
1762 1 : switch (krb5_fwd) {
1763 0 : case CRED_AUTO_KRB_FORWARDABLE:
1764 0 : return "CRED_AUTO_KRB_FORWARDABLE";
1765 0 : case CRED_NO_KRB_FORWARDABLE:
1766 0 : return "CRED_NO_KRB_FORWARDABLE";
1767 0 : case CRED_FORCE_KRB_FORWARDABLE:
1768 0 : return "CRED_FORCE_KRB_FORWARDABLE";
1769 : }
1770 :
1771 : /* Never reached */
1772 0 : return "";
1773 : }
1774 :
1775 2 : static const char *signing_state_to_str(enum smb_signing_setting signing_state)
1776 : {
1777 2 : switch(signing_state) {
1778 0 : case SMB_SIGNING_IPC_DEFAULT:
1779 0 : return "SMB_SIGNING_IPC_DEFAULT";
1780 1 : case SMB_SIGNING_DEFAULT:
1781 1 : return "SMB_SIGNING_DEFAULT";
1782 0 : case SMB_SIGNING_OFF:
1783 0 : return "SMB_SIGNING_OFF";
1784 0 : case SMB_SIGNING_IF_REQUIRED:
1785 0 : return "SMB_SIGNING_IF_REQUIRED";
1786 0 : case SMB_SIGNING_DESIRED:
1787 0 : return "SMB_SIGNING_DESIRED";
1788 1 : case SMB_SIGNING_REQUIRED:
1789 1 : return "SMB_SIGNING_REQUIRED";
1790 : }
1791 :
1792 : /* Never reached */
1793 0 : return "";
1794 : }
1795 :
1796 1 : static const char *encryption_state_to_str(enum smb_encryption_setting encryption_state)
1797 : {
1798 1 : switch(encryption_state) {
1799 0 : case SMB_ENCRYPTION_DEFAULT:
1800 0 : return "SMB_ENCRYPTION_DEFAULT";
1801 0 : case SMB_ENCRYPTION_OFF:
1802 0 : return "SMB_ENCRYPTION_OFF";
1803 0 : case SMB_ENCRYPTION_IF_REQUIRED:
1804 0 : return "SMB_ENCRYPTION_IF_REQUIRED";
1805 0 : case SMB_ENCRYPTION_DESIRED:
1806 0 : return "SMB_ENCRYPTION_DESIRED";
1807 0 : case SMB_ENCRYPTION_REQUIRED:
1808 0 : return "SMB_ENCRYPTION_REQUIRED";
1809 : }
1810 :
1811 : /* Never reached */
1812 0 : return "";
1813 : }
1814 :
1815 1 : _PUBLIC_ void cli_credentials_dump(struct cli_credentials *creds)
1816 : {
1817 1 : DBG_ERR("CLI_CREDENTIALS:\n");
1818 1 : DBG_ERR("\n");
1819 2 : DBG_ERR(" Username: %s - %s\n",
1820 : creds->username,
1821 : obtained_to_str(creds->username_obtained));
1822 1 : DBG_ERR(" Workstation: %s - %s\n",
1823 : creds->workstation,
1824 : obtained_to_str(creds->workstation_obtained));
1825 2 : DBG_ERR(" Domain: %s - %s\n",
1826 : creds->domain,
1827 : obtained_to_str(creds->domain_obtained));
1828 2 : DBG_ERR(" Password: %s - %s\n",
1829 : creds->password != NULL ? "*SECRET*" : "NULL",
1830 : obtained_to_str(creds->password_obtained));
1831 2 : DBG_ERR(" Old password: %s\n",
1832 : creds->old_password != NULL ? "*SECRET*" : "NULL");
1833 1 : DBG_ERR(" Password tries: %u\n",
1834 : creds->password_tries);
1835 1 : DBG_ERR(" Realm: %s - %s\n",
1836 : creds->realm,
1837 : obtained_to_str(creds->realm_obtained));
1838 1 : DBG_ERR(" Principal: %s - %s\n",
1839 : creds->principal,
1840 : obtained_to_str(creds->principal_obtained));
1841 1 : DBG_ERR(" Salt principal: %s\n",
1842 : creds->salt_principal);
1843 1 : DBG_ERR(" Impersonate principal: %s\n",
1844 : creds->impersonate_principal);
1845 1 : DBG_ERR(" Self service: %s\n",
1846 : creds->self_service);
1847 1 : DBG_ERR(" Target service: %s\n",
1848 : creds->target_service);
1849 2 : DBG_ERR(" Kerberos state: %s - %s\n",
1850 : krb5_state_to_str(creds->kerberos_state),
1851 : obtained_to_str(creds->kerberos_state_obtained));
1852 1 : DBG_ERR(" Kerberos forwardable ticket: %s\n",
1853 : krb5_fwd_to_str(creds->krb_forwardable));
1854 2 : DBG_ERR(" Signing state: %s - %s\n",
1855 : signing_state_to_str(creds->signing_state),
1856 : obtained_to_str(creds->signing_state_obtained));
1857 2 : DBG_ERR(" IPC signing state: %s - %s\n",
1858 : signing_state_to_str(creds->ipc_signing_state),
1859 : obtained_to_str(creds->ipc_signing_state_obtained));
1860 1 : DBG_ERR(" Encryption state: %s - %s\n",
1861 : encryption_state_to_str(creds->encryption_state),
1862 : obtained_to_str(creds->encryption_state_obtained));
1863 1 : DBG_ERR(" Gensec features: %#X\n",
1864 : creds->gensec_features);
1865 1 : DBG_ERR(" Forced sasl mech: %s\n",
1866 : creds->forced_sasl_mech);
1867 1 : DBG_ERR(" CCACHE: %p - %s\n",
1868 : creds->ccache,
1869 : obtained_to_str(creds->ccache_obtained));
1870 1 : DBG_ERR(" CLIENT_GSS_CREDS: %p - %s\n",
1871 : creds->client_gss_creds,
1872 : obtained_to_str(creds->client_gss_creds_obtained));
1873 1 : DBG_ERR(" SERVER_GSS_CREDS: %p - %s\n",
1874 : creds->server_gss_creds,
1875 : obtained_to_str(creds->server_gss_creds_obtained));
1876 1 : DBG_ERR(" KEYTAB: %p - %s\n",
1877 : creds->keytab,
1878 : obtained_to_str(creds->keytab_obtained));
1879 1 : DBG_ERR(" KVNO: %u\n",
1880 : creds->kvno);
1881 1 : DBG_ERR("\n");
1882 1 : }
1883 :
1884 : /**
1885 : * @brief Obtain the SMB encryption state from a credentials structure.
1886 : *
1887 : * @param[in] creds The credential structure to obtain the SMB encryption state
1888 : * from.
1889 : *
1890 : * @return The SMB signing state.
1891 : */
1892 : _PUBLIC_ enum smb_encryption_setting
1893 68820 : cli_credentials_get_smb_encryption(struct cli_credentials *creds)
1894 : {
1895 68820 : return creds->encryption_state;
1896 : }
1897 :
1898 : /**
1899 : * Encrypt a data blob using the session key and the negotiated encryption
1900 : * algorithm
1901 : *
1902 : * @param state Credential state, contains the session key and algorithm
1903 : * @param data Data blob containing the data to be encrypted.
1904 : *
1905 : */
1906 89 : _PUBLIC_ NTSTATUS netlogon_creds_session_encrypt(
1907 : struct netlogon_creds_CredentialState *state,
1908 : DATA_BLOB data)
1909 : {
1910 0 : NTSTATUS status;
1911 :
1912 89 : if (data.data == NULL || data.length == 0) {
1913 0 : DBG_ERR("Nothing to encrypt "
1914 : "data.data == NULL or data.length == 0\n");
1915 0 : return NT_STATUS_INVALID_PARAMETER;
1916 : }
1917 : /*
1918 : * Don't crypt an all-zero password it will give away the
1919 : * NETLOGON pipe session key .
1920 : */
1921 89 : if (all_zero(data.data, data.length)) {
1922 0 : DBG_ERR("Supplied data all zeros, could leak session key\n");
1923 0 : return NT_STATUS_INVALID_PARAMETER;
1924 : }
1925 89 : if (state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1926 89 : status = netlogon_creds_aes_encrypt(state,
1927 : data.data,
1928 : data.length);
1929 0 : } else if (state->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1930 0 : status = netlogon_creds_arcfour_crypt(state,
1931 : data.data,
1932 : data.length);
1933 : } else {
1934 0 : DBG_ERR("Unsupported encryption option negotiated\n");
1935 0 : status = NT_STATUS_NOT_SUPPORTED;
1936 : }
1937 89 : if (!NT_STATUS_IS_OK(status)) {
1938 0 : return status;
1939 : }
1940 89 : return NT_STATUS_OK;
1941 : }
1942 :
|