bool SmbAuthenticate(char* name, char* password, char* domainname, char* groupname, UINT timeout, UCHAR* challenge8, UCHAR* MsChapV2_ClientResponse, UCHAR* nt_pw_hash_hash) { bool auth = false; int fds[2]; FILE* out, *in; PID pid; char buffer[255]; char ntlm_timeout[32]; char* proc_parameter[6]; if (name == NULL || password == NULL || domainname == NULL || groupname == NULL) { Debug("Sam.c - SmbAuthenticate - wrong password parameter\n"); return false; } if (password[0] == '\0' && (challenge8 == NULL || MsChapV2_ClientResponse == NULL || nt_pw_hash_hash == NULL)) { Debug("Sam.c - SmbAuthenticate - wrong MsCHAPv2 parameter\n"); return false; } Zero(buffer, sizeof(buffer)); // Truncate string if unsafe char EnSafeStr(domainname, '\0'); if (strlen(domainname) > 255) { // there is no domainname longer then 255 chars! // http://tools.ietf.org/html/rfc1035 section 2.3.4 domainname[255] = '\0'; } // set timeout to 15 minutes even if timeout is disabled, to prevent ntlm_auth from hung up if (timeout <= 0 || timeout > 900) { timeout = 999; } snprintf(ntlm_timeout, sizeof(ntlm_timeout), "%is", timeout); Debug("Sam.c - timeout for ntlm_auth %s\n", ntlm_timeout); proc_parameter[0] = "timeout"; proc_parameter[1] = ntlm_timeout; proc_parameter[2] = "ntlm_auth"; proc_parameter[3] = "--helper-protocol=ntlm-server-1"; proc_parameter[4] = 0; if (strlen(groupname) > 1) { // DNS Name 255 chars + OU names are limited to 64 characters + cmdline 32 + 1 char requiremember[352]; // Truncate string if unsafe char EnSafeStr(groupname, '\0'); snprintf(requiremember, sizeof(requiremember), "--require-membership-of=%s\\%s", domainname, groupname); proc_parameter[4] = requiremember; proc_parameter[5] = 0; } pid = OpenChildProcess("timeout", proc_parameter, fds); if (pid < 0) { Debug("Sam.c - SmbCheckLogon - error fork child process (ntlm_auth)\n"); return false; } out = fdopen(fds[1], "w"); if (out == 0) { CloseChildProcess(pid, fds); Debug("Sam.c - cant open out pipe (ntlm_auth)\n"); return false; } in = fdopen(fds[0], "r"); if (in == 0) { fclose(out); CloseChildProcess(pid, fds); Debug("Sam.c - cant open in pipe (ntlm_auth)\n"); return false; } if (base64_enc_len(strlen(name)) < sizeof(buffer)-1 && base64_enc_len(strlen(password)) < sizeof(buffer)-1 && base64_enc_len(strlen(domainname)) < sizeof(buffer)-1) { char answer[300]; unsigned int end = B64_Encode(buffer, name, strlen(name)); buffer[end] = '\0'; fputs("Username:: ", out); fputs(buffer, out); fputs("\n", out); Debug("Username: %s\n", buffer); buffer[0] = 0; end = B64_Encode(buffer, domainname, strlen(domainname)); buffer[end] = '\0'; fputs("NT-Domain:: ", out); fputs(buffer, out); fputs("\n", out); Debug("NT-Domain: %s\n", buffer); buffer[0] = 0; if (password[0] != '\0') { Debug("Password authentication\n"); end = B64_Encode(buffer, password, strlen(password)); buffer[end] = '\0'; fputs("Password:: ", out); fputs(buffer, out); fputs("\n", out); Debug("Password: %s\n", buffer); buffer[0] = 0; } else { char* mschapv2_client_response; char* base64_challenge8; Debug("MsChapV2 authentication\n"); mschapv2_client_response = CopyBinToStr(MsChapV2_ClientResponse, 24); end = B64_Encode(buffer, mschapv2_client_response, 48); buffer[end] = '\0'; fputs("NT-Response:: ", out); fputs(buffer, out); fputs("\n", out); Debug("NT-Response:: %s\n", buffer); buffer[0] = 0; Free(mschapv2_client_response); base64_challenge8 = CopyBinToStr(challenge8, 8); end = B64_Encode(buffer, base64_challenge8 , 16); buffer[end] = '\0'; fputs("LANMAN-Challenge:: ", out); fputs(buffer, out); fputs("\n", out); Debug("LANMAN-Challenge:: %s\n", buffer); buffer[0] = 0; Free(base64_challenge8); fputs("Request-User-Session-Key: Yes\n", out); } // Start authentication fputs( ".\n", out ); fflush (out); // Request send! Zero(answer, sizeof(answer)); while (fgets(answer, sizeof(answer)-1, in)) { char* response_parameter; if (strncmp(answer, ".\n", sizeof(answer)-1 ) == 0) { break; } /* Indicates a base64 encoded structure */ response_parameter = strstr(answer, ":: "); if (!response_parameter) { char* newline; response_parameter = strstr(answer, ": "); if (!response_parameter) { continue; } response_parameter[0] ='\0'; response_parameter++; response_parameter[0] ='\0'; response_parameter++; newline = strstr(response_parameter, "\n"); if( newline ) newline[0] = '\0'; } else { response_parameter[0] ='\0'; response_parameter++; response_parameter[0] ='\0'; response_parameter++; response_parameter[0] ='\0'; response_parameter++; end = Decode64(response_parameter, response_parameter); response_parameter[end] = '\0'; } if (strncmp(answer, "Authenticated", sizeof(answer)-1 ) == 0) { if (strcmp(response_parameter, "Yes") == 0) { Debug("Authenticated!\n"); auth = true; } else if (strcmp(response_parameter, "No") == 0) { Debug("Authentication failed!\n"); auth = false; } } else if (strncmp(answer, "User-Session-Key", sizeof(answer)-1 ) == 0) { if (nt_pw_hash_hash != NULL) { BUF* Buf = StrToBin(response_parameter); Copy(nt_pw_hash_hash, Buf->Buf, 16); FreeBuf(Buf); } } } } fclose(in); fclose(out); CloseChildProcess(pid, fds); return auth; }
// Enumeration of the secure objects LIST *EnumSecObject(SECURE *sec) { CK_BBOOL b_true = true, b_false = false; UINT objects[MAX_OBJ]; UINT i; UINT ret; LIST *o; CK_ATTRIBUTE dummy[1]; CK_ATTRIBUTE a[] = { {CKA_TOKEN, &b_true, sizeof(b_true)}, }; UINT num_objects = MAX_OBJ; // Validate arguments if (sec == NULL) { return NULL; } if (sec->SessionCreated == false) { sec->Error = SEC_ERROR_NO_SESSION; return NULL; } Zero(dummy, sizeof(dummy)); // If there is a cache, return it if (sec->EnumCache != NULL) { return CloneEnumSecObject(sec->EnumCache); } // Enumerate // if (sec->Dev->Id != 2 && sec->Dev->Id != 14) // { // Normal tokens ret = sec->Api->C_FindObjectsInit(sec->SessionId, a, sizeof(a) / sizeof(a[0])); // } // else // { // ePass and SafeSign // ret = sec->Api->C_FindObjectsInit(sec->SessionId, dummy, 0); // } if (ret != CKR_OK) { sec->Error = SEC_ERROR_HARDWARE_ERROR; return NULL; } if (sec->Api->C_FindObjects(sec->SessionId, objects, sizeof(objects) / sizeof(objects[0]), &num_objects) != CKR_OK) { sec->Api->C_FindObjectsFinal(sec->SessionId); sec->Error = SEC_ERROR_HARDWARE_ERROR; return NULL; } sec->Api->C_FindObjectsFinal(sec->SessionId); o = NewListFast(NULL); for (i = 0;i < num_objects;i++) { char label[MAX_SIZE]; UINT obj_class = 0; bool priv = false; CK_ATTRIBUTE get[] = { {CKA_LABEL, label, sizeof(label) - 1}, {CKA_CLASS, &obj_class, sizeof(obj_class)}, {CKA_PRIVATE, &priv, sizeof(priv)}, }; Zero(label, sizeof(label)); if (sec->Api->C_GetAttributeValue(sec->SessionId, objects[i], get, sizeof(get) / sizeof(get[0])) == CKR_OK) { UINT type = INFINITE; switch (obj_class) { case CKO_DATA: // Data type = SEC_DATA; break; case CKO_CERTIFICATE: // Certificate type = SEC_X; break; case CKO_PUBLIC_KEY: // Public key type = SEC_P; break; case CKO_PRIVATE_KEY: // Secret key type = SEC_K; break; } if (type != INFINITE) { SEC_OBJ *obj = ZeroMalloc(sizeof(SEC_OBJ)); obj->Type = type; obj->Object = objects[i]; obj->Private = (priv == false) ? false : true; EnSafeStr(label, '?'); TruncateCharFromStr(label, '?'); obj->Name = CopyStr(label); Add(o, obj); } } } // Creating a cache sec->EnumCache = CloneEnumSecObject(o); return o; }