96int fail_debug_enabled = 0;
104 WCHAR wszUserName[UNLEN+1];
105 WCHAR wszGroup[GNLEN+1];
107 LPLOCALGROUP_USERS_INFO_0 pBuf =
nullptr;
108 LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
110 DWORD dwFlags = LG_INCLUDE_INDIRECT;
111 DWORD dwPrefMaxLen = -1;
112 DWORD dwEntriesRead = 0;
113 DWORD dwTotalEntries = 0;
114 NET_API_STATUS nStatus;
116 DWORD dwTotalCount = 0;
120 MultiByteToWideChar(CP_ACP, 0, UserName,
121 strlen(UserName) + 1, wszUserName,
122 sizeof(wszUserName) /
sizeof(wszUserName[0]));
123 MultiByteToWideChar(CP_ACP, 0, Group,
124 strlen(Group) + 1, wszGroup,
sizeof(wszGroup) /
sizeof(wszGroup[0]));
134 nStatus = NetUserGetLocalGroups(
nullptr,
138 (LPBYTE *) & pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries);
142 if (nStatus == NERR_Success) {
143 if ((pTmpBuf = pBuf) !=
NULL) {
144 for (i = 0; i < dwEntriesRead; ++i) {
145 if (pTmpBuf ==
NULL) {
149 if (wcscmp(pTmpBuf->lgrui0_name, wszGroup) == 0) {
163 NetApiBufferFree(pBuf);
170 static char * target;
172 len = LsaStr.Length/
sizeof(WCHAR) + 1;
181 WideCharToMultiByte(CP_ACP, 0, LsaStr.Buffer, LsaStr.Length, target, len,
nullptr,
nullptr);
184 target[len-1] =
'\0';
191 LSA_HANDLE PolicyHandle;
192 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
194 PPOLICY_PRIMARY_DOMAIN_INFO ppdiDomainInfo;
195 PWKSTA_INFO_100 pwkiWorkstationInfo;
197 char * DomainName =
nullptr;
202 memset(&ObjectAttributes,
'\0',
sizeof(ObjectAttributes));
211 netret = NetWkstaGetInfo(
nullptr, 100, (LPBYTE *)&pwkiWorkstationInfo);
212 if (netret == NERR_Success) {
220 status = LsaOpenPolicy(
223 GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION,
231 debug(
"OpenPolicy Error: %ld\n", status);
238 status = LsaQueryInformationPolicy(PolicyHandle,
239 PolicyPrimaryDomainInformation,
240 (
void **)&ppdiDomainInfo);
242 debug(
"LsaQueryInformationPolicy Error: %ld\n", status);
253 if (ppdiDomainInfo->Sid) {
258 debug(
"Member of Domain %s\n",DomainName);
260 DomainName =
nullptr;
269 NetApiBufferFree(pwkiWorkstationInfo);
270 LsaFreeMemory((LPVOID)ppdiDomainInfo);
272 debug(
"NetWkstaGetInfo Error: %ld\n", netret);
289 if (!NTLM_LocalCall) {
298 if (domain[0] ==
'\0') {
299 debug(
"No domain supplied. Returning no-auth\n");
302 if (user[0] ==
'\0') {
303 debug(
"No username supplied. Returning no-auth\n");
306 debug(
"checking domain: '%s', user: '%s'\n", domain, user);
309 debug(
"checking local user\n");
311 snprintf(
credentials, DNLEN+UNLEN+2,
"%s\\%s", domain, user);
313 rv = SSP_ValidateNTLMCredentials(auth, auth_length,
credentials);
315 debug(
"Login attempt had result %d\n", rv);
342 fail_debug_enabled =1;
360 "Usage: %s [-d] [-v] [-A|D LocalUserGroup] [-h]\n"
361 " -d enable debugging.\n"
362 " -v enable verbose NTLM packet debugging.\n"
363 " -A specify a Windows Local Group name allowed to authenticate\n"
364 " -D specify a Windows Local Group name not allowed to authenticate\n"
365 " -h this message\n\n",
372 int opt, had_error = 0;
375 while (-1 != (opt =
getopt(argc, argv,
"hdvA:D:"))) {
401 fprintf(stderr,
"unknown option: -%c. Exiting\n", opt);
417 SEND_BH(
"message=\"base64 decode failed\"");
418 fprintf(stderr,
"ERROR: base64 decoding failed for: '%s'\n", buf);
430 size_t decodedLen = 0;
431 char helper_command[3];
435 char domain[DNLEN+1];
440 if (memcpy(local_nego.
hdr.
signature,
"NTLMSSP", 8) != 0) {
451 if (fgets(buf,
sizeof(buf), stdin) ==
NULL)
454 char *c =
static_cast<char*
>(memchr(buf,
'\n',
sizeof(buf)));
457 helperfail(
"message=\"illegal request received\"");
458 fprintf(stderr,
"Illegal request received: '%s'\n", buf);
463 fprintf(stderr,
"No newline in '%s'\n", buf);
472 strncpy(helper_command, buf, 2);
473 debug(
"Got '%s' from Squid with data:\n", helper_command);
474 hex_dump(
reinterpret_cast<unsigned char*
>(decoded), decodedLen);
476 debug(
"Got '%s' from Squid\n", buf);
477 if (memcmp(buf,
"YR", 2) == 0) {
479 if (strlen(buf) > 3) {
480 if (!decodedLen && !
token_decode(&decodedLen, decoded, buf+3))
483 debug(
"Negotiate packet not supplied - self generated\n");
484 memcpy(decoded, &local_nego,
sizeof(local_nego));
485 decodedLen =
sizeof(local_nego);
487 if ((
size_t)decodedLen <
sizeof(
ntlmhdr)) {
488 SEND_ERR(
"message=\"Packet format error\"");
492 fast_header = (
struct _ntlmhdr *) decoded;
496 SEND_ERR(
"message=\"Broken authentication packet\"");
499 switch (fast_header->
type) {
502 debug(
"attempting SSPI challenge retrieval\n");
503 char *c = (
char *) SSP_MakeChallenge((
ntlm_negotiate *) decoded, decodedLen);
509 debug(
"send 'TT' to squid with data:\n");
510 hex_dump(
reinterpret_cast<unsigned char*
>(decoded), decodedLen);
511 if (NTLM_LocalCall) {
512 debug(
"NTLM Local Call detected\n");
517 helperfail(
"message=\"can't obtain challenge\"");
523 SEND_ERR(
"message=\"Got a challenge. We refuse to have our authority disputed\"");
527 SEND_ERR(
"message=\"Got authentication request instead of negotiate request\"");
531 helperfail(
"message=\"unknown refresh-request packet type\"");
536 if (memcmp(buf,
"KK ", 3) == 0) {
542 if (!decodedLen && !
token_decode(&decodedLen, decoded, buf+3))
545 if ((
size_t)decodedLen <
sizeof(
ntlmhdr)) {
546 SEND_ERR(
"message=\"Packet format error\"");
550 fast_header = (
struct _ntlmhdr *) decoded;
554 SEND_ERR(
"message=\"Broken authentication packet\"");
557 switch (fast_header->
type) {
559 SEND_ERR(
"message=\"Invalid negotiation request received\"");
563 SEND_ERR(
"message=\"Got a challenge. We refuse to have our authority disputed\"");
572 fail_debug_enabled =1;
578 SEND_ERR(
"message=\"Incorrect Group Membership\"");
581 SEND_ERR(
"message=\"Incorrect Request Format\"");
585 FORMAT_MESSAGE_ALLOCATE_BUFFER |
586 FORMAT_MESSAGE_FROM_SYSTEM |
587 FORMAT_MESSAGE_IGNORE_INSERTS,
590 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
591 (LPTSTR) &ErrorMessage,
594 if (ErrorMessage[strlen(ErrorMessage) - 1] ==
'\n')
595 ErrorMessage[strlen(ErrorMessage) - 1] =
'\0';
596 if (ErrorMessage[strlen(ErrorMessage) - 1] ==
'\r')
597 ErrorMessage[strlen(ErrorMessage) - 1] =
'\0';
599 LocalFree(ErrorMessage);
602 SEND_ERR(
"message=\"Unknown Error\"");
609 fprintf(stdout,
"OK user=\"%s\\%s\"", domain, user);
613 helperfail(
"message=\"unknown authentication packet type\"");
618 helperfail(
"message=\"illegal request received\"");
619 fprintf(stderr,
"Illegal request received: '%s'\n", buf);
622 helperfail(
"message=\"detected protocol error\"");
637 fprintf(stderr,
"FATAL, can't initialize SSPI, exiting.\n");
640 debug(
"SSPI initialized OK\n");
645 setbuf(stdout,
nullptr);
646 setbuf(stderr,
nullptr);
void base64_decode_init(struct base64_decode_ctx *ctx)
int base64_decode_update(struct base64_decode_ctx *ctx, size_t *dst_length, uint8_t *dst, size_t src_length, const char *src)
int base64_decode_final(struct base64_decode_ctx *ctx)
#define HELPER_INPUT_BUFFER
void debug(const char *format,...)
int getopt(int nargc, char *const *nargv, const char *ostr)
static char credentials[MAX_USERNAME_LEN+MAX_DOMAIN_LEN+2]
int NTLM_packet_debug_enabled
static bool token_decode(size_t *decodedLen, uint8_t decoded[], const char *buf)
int main(int argc, char *argv[])
int ntlm_check_auth(ntlm_authenticate *auth, char *user, char *domain, int auth_length)
static int have_challenge
char * AllocStrFromLSAStr(LSA_UNICODE_STRING LsaStr)
void helperfail(const char *reason)
void process_options(int argc, char *argv[])
char * GetDomainName(void)
int Valid_Group(char *UserName, char *Group)
int ntlm_validate_packet(const ntlmhdr *hdr, const int32_t type)
int ntlm_unpack_auth(const ntlm_authenticate *auth, char *user, char *domain, const int32_t size)
#define NTLM_AUTHENTICATE
#define NTLM_NEGOTIATE_USE_NTLM
#define NTLM_NEGOTIATE_USE_LM
#define NTLM_NEGOTIATE_ASCII
#define NTLM_NEGOTIATE_ALWAYS_SIGN
void UnloadSecurityDll(void)
HMODULE LoadSecurityDll(int mode, const char *SSP_Package)
#define NTLM_PACKAGE_NAME
void hex_dump(unsigned char *data, int size)