102 int fail_debug_enabled = 0;
110 WCHAR wszUserName[UNLEN+1];
111 WCHAR wszGroup[GNLEN+1];
113 LPLOCALGROUP_USERS_INFO_0 pBuf =
NULL;
114 LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
116 DWORD dwFlags = LG_INCLUDE_INDIRECT;
117 DWORD dwPrefMaxLen = -1;
118 DWORD dwEntriesRead = 0;
119 DWORD dwTotalEntries = 0;
120 NET_API_STATUS nStatus;
122 DWORD dwTotalCount = 0;
126 MultiByteToWideChar(CP_ACP, 0, UserName,
127 strlen(UserName) + 1, wszUserName,
128 sizeof(wszUserName) /
sizeof(wszUserName[0]));
129 MultiByteToWideChar(CP_ACP, 0, Group,
130 strlen(Group) + 1, wszGroup,
sizeof(wszGroup) /
sizeof(wszGroup[0]));
140 nStatus = NetUserGetLocalGroups(
NULL,
144 (LPBYTE *) & pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries);
148 if (nStatus == NERR_Success) {
149 if ((pTmpBuf = pBuf) !=
NULL) {
150 for (i = 0; i < dwEntriesRead; ++i) {
151 if (pTmpBuf ==
NULL) {
155 if (wcscmp(pTmpBuf->lgrui0_name, wszGroup) == 0) {
169 NetApiBufferFree(pBuf);
176 static char * target;
178 len = LsaStr.Length/
sizeof(WCHAR) + 1;
187 WideCharToMultiByte(CP_ACP, 0, LsaStr.Buffer, LsaStr.Length, target, len,
NULL,
NULL );
190 target[len-1] =
'\0';
197 LSA_HANDLE PolicyHandle;
198 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
200 PPOLICY_PRIMARY_DOMAIN_INFO ppdiDomainInfo;
201 PWKSTA_INFO_100 pwkiWorkstationInfo;
203 char * DomainName =
NULL;
208 memset(&ObjectAttributes,
'\0',
sizeof(ObjectAttributes));
217 netret = NetWkstaGetInfo(
NULL, 100, (LPBYTE *)&pwkiWorkstationInfo);
218 if (netret == NERR_Success) {
226 status = LsaOpenPolicy(
229 GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION,
237 debug(
"OpenPolicy Error: %ld\n", status);
244 status = LsaQueryInformationPolicy(PolicyHandle,
245 PolicyPrimaryDomainInformation,
246 (
void **)&ppdiDomainInfo);
248 debug(
"LsaQueryInformationPolicy Error: %ld\n", status);
259 if (ppdiDomainInfo->Sid) {
264 debug(
"Member of Domain %s\n",DomainName);
275 NetApiBufferFree(pwkiWorkstationInfo);
276 LsaFreeMemory((LPVOID)ppdiDomainInfo);
278 debug(
"NetWkstaGetInfo Error: %ld\n", netret);
304 if (domain[0] ==
'\0') {
305 debug(
"No domain supplied. Returning no-auth\n");
308 if (user[0] ==
'\0') {
309 debug(
"No username supplied. Returning no-auth\n");
312 debug(
"checking domain: '%s', user: '%s'\n", domain, user);
315 debug(
"checking local user\n");
317 snprintf(
credentials, DNLEN+UNLEN+2,
"%s\\%s", domain, user);
321 debug(
"Login attempt had result %d\n", rv);
348 fail_debug_enabled =1;
366 "Usage: %s [-d] [-v] [-A|D LocalUserGroup] [-h]\n"
367 " -d enable debugging.\n"
368 " -v enable verbose NTLM packet debugging.\n"
369 " -A specify a Windows Local Group name allowed to authenticate\n"
370 " -D specify a Windows Local Group name not allowed to authenticate\n"
371 " -h this message\n\n",
378 int opt, had_error = 0;
381 while (-1 != (opt =
getopt(argc, argv,
"hdvA:D:"))) {
407 fprintf(stderr,
"unknown option: -%c. Exiting\n", opt);
423 SEND_BH(
"message=\"base64 decode failed\"");
424 fprintf(stderr,
"ERROR: base64 decoding failed for: '%s'\n", buf);
436 size_t decodedLen = 0;
437 char helper_command[3];
441 char domain[DNLEN+1];
446 if (memcpy(local_nego.
hdr.
signature,
"NTLMSSP", 8) != 0) {
457 if (fgets(buf,
sizeof(buf), stdin) ==
NULL)
460 char *c =
static_cast<char*
>(memchr(buf,
'\n',
sizeof(buf)));
463 helperfail(
"message=\"illegal request received\"");
464 fprintf(stderr,
"Illegal request received: '%s'\n", buf);
469 fprintf(stderr,
"No newline in '%s'\n", buf);
478 strncpy(helper_command, buf, 2);
479 debug(
"Got '%s' from Squid with data:\n", helper_command);
480 hex_dump(
reinterpret_cast<unsigned char*
>(decoded), decodedLen);
482 debug(
"Got '%s' from Squid\n", buf);
483 if (memcmp(buf,
"YR", 2) == 0) {
485 if (strlen(buf) > 3) {
486 if (!decodedLen && !
token_decode(&decodedLen, decoded, buf+3))
489 debug(
"Negotiate packet not supplied - self generated\n");
490 memcpy(decoded, &local_nego,
sizeof(local_nego));
491 decodedLen =
sizeof(local_nego);
493 if ((
size_t)decodedLen <
sizeof(
ntlmhdr)) {
494 SEND_ERR(
"message=\"Packet format error\"");
498 fast_header = (
struct _ntlmhdr *) decoded;
502 SEND_ERR(
"message=\"Broken authentication packet\"");
505 switch (fast_header->
type) {
508 debug(
"attempting SSPI challenge retrieval\n");
515 debug(
"send 'TT' to squid with data:\n");
516 hex_dump(
reinterpret_cast<unsigned char*
>(decoded), decodedLen);
518 debug(
"NTLM Local Call detected\n");
523 helperfail(
"message=\"can't obtain challenge\"");
529 SEND_ERR(
"message=\"Got a challenge. We refuse to have our authority disputed\"");
533 SEND_ERR(
"message=\"Got authentication request instead of negotiate request\"");
537 helperfail(
"message=\"unknown refresh-request packet type\"");
542 if (memcmp(buf,
"KK ", 3) == 0) {
548 if (!decodedLen && !
token_decode(&decodedLen, decoded, buf+3))
551 if ((
size_t)decodedLen <
sizeof(
ntlmhdr)) {
552 SEND_ERR(
"message=\"Packet format error\"");
556 fast_header = (
struct _ntlmhdr *) decoded;
560 SEND_ERR(
"message=\"Broken authentication packet\"");
563 switch (fast_header->
type) {
565 SEND_ERR(
"message=\"Invalid negotiation request received\"");
569 SEND_ERR(
"message=\"Got a challenge. We refuse to have our authority disputed\"");
578 fail_debug_enabled =1;
584 SEND_ERR(
"message=\"Incorrect Group Membership\"");
587 SEND_ERR(
"message=\"Incorrect Request Format\"");
591 FORMAT_MESSAGE_ALLOCATE_BUFFER |
592 FORMAT_MESSAGE_FROM_SYSTEM |
593 FORMAT_MESSAGE_IGNORE_INSERTS,
596 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
597 (LPTSTR) &ErrorMessage,
600 if (ErrorMessage[strlen(ErrorMessage) - 1] ==
'\n')
601 ErrorMessage[strlen(ErrorMessage) - 1] =
'\0';
602 if (ErrorMessage[strlen(ErrorMessage) - 1] ==
'\r')
603 ErrorMessage[strlen(ErrorMessage) - 1] =
'\0';
605 LocalFree(ErrorMessage);
608 SEND_ERR(
"message=\"Unknown Error\"");
615 fprintf(stdout,
"OK user=\"%s\\%s\"", domain, user);
619 helperfail(
"message=\"unknown authentication packet type\"");
624 helperfail(
"message=\"illegal request received\"");
625 fprintf(stderr,
"Illegal request received: '%s'\n", buf);
628 helperfail(
"message=\"detected protocol error\"");
643 fprintf(stderr,
"FATAL, can't initialize SSPI, exiting.\n");
646 debug(
"SSPI initialized OK\n");
651 setbuf(stdout,
NULL);
652 setbuf(stderr,
NULL);
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
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
void helperfail(const char *reason)
char * AllocStrFromLSAStr(LSA_UNICODE_STRING LsaStr)
void process_options(int argc, char *argv[])
int Valid_Group(char *UserName, char *Group)
char * GetDomainName(void)
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
BOOL WINAPI SSP_ValidateNTLMCredentials(PVOID PAutenticateBuf, int AutenticateLen, char *credentials)
const char *WINAPI SSP_MakeChallenge(PVOID PNegotiateBuf, int NegotiateLen)
void UnloadSecurityDll(void)
HMODULE LoadSecurityDll(int mode, const char *SSP_Package)
void hex_dump(unsigned char *data, int size)