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