22 |
22 |
#include "smblib/smblib.h"
|
23 |
23 |
//#include "util.h"
|
|
24 |
#define MAX_DOMAIN_LEN 255
|
|
25 |
|
24 |
26 |
#if HAVE_STRING_H
|
25 |
27 |
#include <string.h>
|
26 |
28 |
#endif
|
... | ... | |
91 |
93 |
void usage(void);
|
92 |
94 |
void process_options(int argc, char *argv[]);
|
93 |
95 |
const char * obtain_challenge(void);
|
94 |
|
void manage_request(void);
|
|
96 |
int manage_request(void);
|
|
97 |
int choose_dc(ntlm_authenticate * auth, int plen, int type);
|
95 |
98 |
#define ENCODED_PASS_LEN 24
|
96 |
99 |
#define MAX_USERNAME_LEN 255
|
... | ... | |
109 |
112 |
#if DEBUG
|
110 |
113 |
char error_messages_buffer[NTLM_BLOB_BUFFER_SIZE];
|
111 |
114 |
#endif
|
|
115 |
|
|
116 |
int any_controller = 0; /* To authenticate on any available controller, default: NO */
|
112 |
117 |
char load_balance = 0, protocol_pedantic = 0;
|
113 |
118 |
dc *controllers = NULL;
|
114 |
119 |
int numcontrollers = 0;
|
... | ... | |
337 |
342 |
{
|
338 |
343 |
fprintf(stderr,
|
339 |
344 |
"%s usage:\n%s [-b] [-f] [-d] [-l] domain\\controller [domain\\controller ...]\n"
|
|
345 |
"-a any valid authentication on one of the domain controllers is enough to authenticate\n"
|
340 |
346 |
"-b enables load-balancing among controllers\n"
|
341 |
347 |
"-f enables failover among controllers (DEPRECATED and always active)\n"
|
342 |
348 |
"-d enables debugging statements if DEBUG was defined at build-time.\n\n"
|
... | ... | |
353 |
359 |
{
|
354 |
360 |
int opt, j, had_error = 0;
|
355 |
361 |
dc *new_dc = NULL, *last_dc = NULL;
|
356 |
|
while (-1 != (opt = getopt(argc, argv, "bfld"))) {
|
|
362 |
while (-1 != (opt = getopt(argc, argv, "abfld"))) {
|
357 |
363 |
switch (opt) {
|
|
364 |
case 'a':
|
|
365 |
any_controller = 1;
|
|
366 |
break;
|
358 |
367 |
case 'b':
|
359 |
368 |
load_balance = 1;
|
360 |
369 |
break;
|
... | ... | |
465 |
474 |
return NULL;
|
466 |
475 |
}
|
467 |
|
void
|
|
476 |
int
|
|
477 |
choose_dc(ntlm_authenticate * auth, int plen, int type)
|
|
478 |
{
|
|
479 |
/* This function extracts the domain from the decoded message (type 1
|
|
480 |
* (negotiate) or type 3 (authenticate)) and modifies the global variable
|
|
481 |
* current_dc accordingly. */
|
|
482 |
int i;
|
|
483 |
char domain[MAX_DOMAIN_LEN+2];
|
|
484 |
lstring tmp;
|
|
485 |
|
|
486 |
/* Extract domain from decoded message: */
|
|
487 |
switch (type) {
|
|
488 |
case NTLM_NEGOTIATE:
|
|
489 |
tmp = ntlm_fetch_string(&(auth->hdr), plen, &auth->domain, auth->flags);
|
|
490 |
break;
|
|
491 |
case NTLM_AUTHENTICATE:
|
|
492 |
tmp = ntlm_fetch_string(&(auth->hdr), plen, &auth->domain, auth->flags);
|
|
493 |
break;
|
|
494 |
default:
|
|
495 |
fprintf(stderr, "Unknown requested type (%d) in choose_dc.\n",
|
|
496 |
type);
|
|
497 |
return 101;
|
|
498 |
}
|
|
499 |
if (tmp.str == NULL || tmp.l == 0) {
|
|
500 |
debug("No domain supplied. Returning no-auth\n");
|
|
501 |
return NTLM_ERR_LOGON;
|
|
502 |
}
|
|
503 |
if (tmp.l > MAX_DOMAIN_LEN) {
|
|
504 |
debug("Domain string exceeds %d bytes, rejecting\n", MAX_DOMAIN_LEN);
|
|
505 |
return NTLM_ERR_LOGON;
|
|
506 |
}
|
|
507 |
if (tmp.l > MAX_DOMAIN_LEN || tmp.l <= 0) return 111;
|
|
508 |
memcpy(domain, tmp.str, tmp.l);
|
|
509 |
domain[tmp.l] = '\0';
|
|
510 |
|
|
511 |
/* Select a dc according to the domain fetched above: */
|
|
512 |
for (i = 0; i < numcontrollers &&
|
|
513 |
memcmp(domain, current_dc->domain, tmp.l) != 0; i++) {
|
|
514 |
current_dc = current_dc->next;
|
|
515 |
}
|
|
516 |
|
|
517 |
/* Check the result: */
|
|
518 |
if (memcmp(domain, current_dc->domain, tmp.l) != 0) {
|
|
519 |
fprintf(stderr, "dc for %s not found (current_dc:%s)!\n",
|
|
520 |
domain, current_dc->domain);
|
|
521 |
return 121; /* Failure. */
|
|
522 |
}
|
|
523 |
return 0; /* Success. */
|
|
524 |
}
|
|
525 |
|
|
526 |
int
|
468 |
527 |
manage_request()
|
469 |
528 |
{
|
470 |
529 |
ntlmhdr *fast_header;
|
... | ... | |
493 |
552 |
if ((size_t)decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */
|
494 |
553 |
SEND("NA Packet format error, couldn't base64-decode");
|
495 |
|
return;
|
|
554 |
return NTLM_ERR_BAD_PROTOCOL;
|
496 |
555 |
}
|
497 |
556 |
/* fast-track-decode request type. */
|
498 |
557 |
fast_header = (ntlmhdr *) decoded;
|
... | ... | |
501 |
560 |
/* sanity-check: it IS a NTLMSSP packet, isn't it? */
|
502 |
561 |
if (ntlm_validate_packet(fast_header, NTLM_ANY) < 0) {
|
503 |
562 |
SEND("NA Broken authentication packet");
|
504 |
|
return;
|
|
563 |
return NTLM_ERR_BAD_PROTOCOL;
|
505 |
564 |
}
|
506 |
565 |
switch (le32toh(fast_header->type)) {
|
507 |
566 |
case NTLM_NEGOTIATE:
|
508 |
567 |
SEND("NA Invalid negotiation request received");
|
509 |
|
return;
|
|
568 |
return NTLM_ERR_BAD_PROTOCOL;
|
510 |
569 |
/* notreached */
|
511 |
570 |
case NTLM_CHALLENGE:
|
512 |
571 |
SEND("NA Got a challenge. We refuse to have our authority disputed");
|
513 |
|
return;
|
|
572 |
return NTLM_ERR_BAD_PROTOCOL;
|
514 |
573 |
/* notreached */
|
515 |
574 |
case NTLM_AUTHENTICATE:
|
516 |
575 |
/* check against the DC */
|
517 |
576 |
signal(SIGALRM, timeout_during_auth);
|
518 |
577 |
alarm(30);
|
|
578 |
if (any_controller) {
|
|
579 |
choose_dc((ntlm_authenticate *) decoded, decodedLen, NTLM_AUTHENTICATE);
|
|
580 |
}
|
519 |
581 |
cred = ntlm_check_auth((ntlm_authenticate *) decoded, decodedLen);
|
520 |
582 |
alarm(0);
|
521 |
583 |
signal(SIGALRM, SIG_DFL);
|
... | ... | |
523 |
585 |
fprintf(stderr, "ntlm-auth[%ld]: Timeout during authentication.\n", (long)getpid());
|
524 |
586 |
SEND("BH Timeout during authentication");
|
525 |
587 |
got_timeout = 0;
|
526 |
|
return;
|
|
588 |
return NTLM_ERR_SERVER;
|
527 |
589 |
}
|
528 |
590 |
if (cred == NULL) {
|
529 |
591 |
int smblib_err, smb_errorclass, smb_errorcode, nb_error;
|
530 |
592 |
if (ntlm_errno == NTLM_ERR_LOGON) { /* hackish */
|
531 |
593 |
SEND("NA Logon Failure");
|
532 |
|
return;
|
|
594 |
return NTLM_ERR_SERVER;
|
533 |
595 |
}
|
534 |
596 |
/* there was an error. We have two errno's to look at.
|
535 |
597 |
* libntlmssp's erno is insufficient, we'll have to look at
|
... | ... | |
547 |
609 |
SEND("BH NetBios error!");
|
548 |
610 |
fprintf(stderr, "NetBios error code %d (%s)\n", nb_error,
|
549 |
611 |
RFCNB_Error_Strings[abs(nb_error)]);
|
550 |
|
return;
|
|
612 |
return NTLM_ERR_SERVER;
|
551 |
613 |
}
|
552 |
614 |
switch (smb_errorclass) {
|
553 |
615 |
case SMBC_SUCCESS:
|
554 |
616 |
debug("Huh? Got a SMB success code but could check auth..");
|
555 |
617 |
SEND("NA Authentication failed");
|
556 |
|
return;
|
|
618 |
return NTLM_ERR_LOGON;
|
557 |
619 |
case SMBC_ERRDOS:
|
558 |
620 |
/*this is the most important one for errors */
|
559 |
621 |
debug("DOS error\n");
|
... | ... | |
562 |
624 |
* server errors, and those which are auth errors */
|
563 |
625 |
case SMBD_noaccess: /* 5 */
|
564 |
626 |
SEND("NA Access denied");
|
565 |
|
return;
|
|
627 |
return NTLM_ERR_LOGON;
|
566 |
628 |
case SMBD_badformat:
|
567 |
629 |
SEND("NA bad format in authentication packet");
|
568 |
|
return;
|
|
630 |
return NTLM_ERR_LOGON;
|
569 |
631 |
case SMBD_badaccess:
|
570 |
632 |
SEND("NA Bad access request");
|
571 |
|
return;
|
|
633 |
return NTLM_ERR_LOGON;
|
572 |
634 |
case SMBD_baddata:
|
573 |
635 |
SEND("NA Bad Data");
|
574 |
|
return;
|
|
636 |
return NTLM_ERR_LOGON;
|
575 |
637 |
default:
|
576 |
638 |
SEND("BH DOS Error");
|
577 |
|
return;
|
|
639 |
return NTLM_ERR_LOGON;
|
578 |
640 |
}
|
579 |
641 |
case SMBC_ERRSRV: /* server errors */
|
580 |
642 |
debug("Server error");
|
... | ... | |
582 |
644 |
/* mostly same as above */
|
583 |
645 |
case SMBV_badpw:
|
584 |
646 |
SEND("NA Bad password");
|
585 |
|
return;
|
|
647 |
return NTLM_ERR_LOGON;
|
586 |
648 |
case SMBV_access:
|
587 |
649 |
SEND("NA Server access error");
|
588 |
|
return;
|
|
650 |
return NTLM_ERR_SERVER;
|
589 |
651 |
default:
|
590 |
652 |
SEND("BH Server Error");
|
591 |
|
return;
|
|
653 |
return NTLM_ERR_SERVER;
|
592 |
654 |
}
|
593 |
655 |
case SMBC_ERRHRD: /* hardware errors don't really matter */
|
594 |
656 |
SEND("BH Domain Controller Hardware error");
|
595 |
|
return;
|
|
657 |
return NTLM_ERR_SERVER;
|
596 |
658 |
case SMBC_ERRCMD:
|
597 |
659 |
SEND("BH Domain Controller Command Error");
|
598 |
|
return;
|
|
660 |
return NTLM_ERR_SERVER;
|
599 |
661 |
}
|
600 |
662 |
SEND("BH unknown internal error.");
|
601 |
|
return;
|
|
663 |
return NTLM_ERR_SERVER;
|
602 |
664 |
}
|
603 |
665 |
lc(cred); /* let's lowercase them for our convenience */
|
604 |
666 |
SEND2("AF %s", cred);
|
605 |
|
return;
|
|
667 |
return NTLM_ERR_NONE;
|
606 |
668 |
default:
|
607 |
669 |
SEND("BH unknown authentication packet type");
|
608 |
|
return;
|
|
670 |
return NTLM_ERR_BAD_PROTOCOL;
|
609 |
671 |
}
|
610 |
672 |
/* notreached */
|
611 |
|
return;
|
|
673 |
return NTLM_ERR_PROTOCOL; /* The 'authenticate request' did not match any of the above */
|
612 |
674 |
}
|
613 |
675 |
if (memcmp(buf, "YR", 2) == 0) { /* refresh-request */
|
|
676 |
if (any_controller) {
|
|
677 |
choose_dc((ntlm_authenticate *) decoded, base64_decode(decoded, sizeof(decoded), buf+3), NTLM_NEGOTIATE);
|
|
678 |
}
|
614 |
679 |
dc_disconnect();
|
615 |
680 |
ch = obtain_challenge();
|
616 |
681 |
/* Robert says we can afford to wait forever. I'll trust him on this
|
... | ... | |
621 |
686 |
ch = obtain_challenge();
|
622 |
687 |
}
|
623 |
688 |
SEND2("TT %s", ch);
|
624 |
|
return;
|
|
689 |
return NTLM_ERR_NONE;
|
625 |
690 |
}
|
626 |
691 |
SEND("BH Helper detected protocol error");
|
627 |
|
return;
|
|
692 |
return NTLM_ERR_PROTOCOL;
|
628 |
693 |
/********* END ********/
|
629 |
694 |
}
|
... | ... | |
639 |
704 |
debug("options processed OK\n");
|
|
705 |
if ( load_balance && any_controller ) {
|
|
706 |
fprintf(stderr, "Cannot both load balance AND do authentication on any controller, exiting\n");
|
|
707 |
exit(1);
|
|
708 |
}
|
|
709 |
|
640 |
710 |
/* initialize FDescs */
|
641 |
711 |
setbuf(stdout, NULL);
|
642 |
712 |
setbuf(stderr, NULL);
|