/* * Simplification wrapper arround AcquireCredentialsHandle as most of * the parameters do not change. */ static int acquireCredentialsHandle(CredHandle * credentials, char *package) { SECURITY_STATUS status; TimeStamp timestamp; status = pSFT->AcquireCredentialsHandleA(NULL, package, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, credentials, ×tamp); if (status != SEC_E_OK) { NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: AcquireCredentialsHandle [fail] [%x].\n", status); return -1; } return 0; }
static bool spAcquireCredentials(bool iVerify, bool iCheckName, CredHandle& oCredHandle) { SCHANNEL_CRED theSCC = {}; theSCC.dwVersion = SCHANNEL_CRED_VERSION; theSCC.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS | 0xA00; theSCC.dwFlags = SCH_CRED_NO_DEFAULT_CREDS; if (not iVerify) theSCC.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; else if (not iCheckName) theSCC.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; return SEC_E_OK == spPSFT->AcquireCredentialsHandleA( nullptr, const_cast<SEC_CHAR*>(UNISP_NAME_A), SECPKG_CRED_OUTBOUND, nullptr, &theSCC, nullptr, nullptr, &oCredHandle, nullptr); }
/** * Build a SSPI packet to send to server * @param tds A pointer to the TDSSOCKET structure managing a client/server operation. */ TDSAUTHENTICATION * tds_sspi_get_auth(TDSSOCKET * tds) { SecBuffer buf; SecBufferDesc desc; SECURITY_STATUS status; ULONG attrs; TimeStamp ts; SEC_WINNT_AUTH_IDENTITY identity; const char *p, *user_name, *server_name; TDSSSPIAUTH *auth; TDSCONNECTION *connection = tds->connection; /* check connection */ if (!connection) return NULL; if (!tds_init_secdll()) return NULL; /* parse username/password informations */ memset(&identity, 0, sizeof(identity)); user_name = tds_dstr_cstr(&connection->user_name); if ((p = strchr(user_name, '\\')) != NULL) { identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; identity.Password = (void *) tds_dstr_cstr(&connection->password); identity.PasswordLength = tds_dstr_len(&connection->password); identity.Domain = (void *) user_name; identity.DomainLength = p - user_name; user_name = p + 1; identity.User = (void *) user_name; identity.UserLength = strlen(user_name); } auth = (TDSSSPIAUTH *) calloc(1, sizeof(TDSSSPIAUTH)); if (!auth || !tds->connection) return NULL; auth->tds_auth.free = tds_sspi_free; auth->tds_auth.handle_next = tds_sspi_handle_next; /* using Negotiate system will use proper protocol (either NTLM or Kerberos) */ if (sec_fn->AcquireCredentialsHandleA(NULL, (char *)"Negotiate", SECPKG_CRED_OUTBOUND, NULL, identity.Domain ? &identity : NULL, NULL, NULL, &auth->cred, &ts) != SEC_E_OK) { free(auth); return NULL; } /* allocate buffer */ auth->tds_auth.packet = (TDS_UCHAR *) malloc(NTLMBUF_LEN); if (!auth->tds_auth.packet) { sec_fn->FreeCredentialsHandle(&auth->cred); free(auth); return NULL; } desc.ulVersion = SECBUFFER_VERSION; desc.cBuffers = 1; desc.pBuffers = &buf; buf.cbBuffer = NTLMBUF_LEN; buf.BufferType = SECBUFFER_TOKEN; buf.pvBuffer = auth->tds_auth.packet; /* build SPN */ server_name = tds_dstr_cstr(&connection->server_host_name); if (strchr(server_name, '.') == NULL) { struct hostent *host = gethostbyname(server_name); if (host && strchr(host->h_name, '.') != NULL) server_name = host->h_name; } if (strchr(server_name, '.') != NULL) { if (asprintf(&auth->sname, "MSSQLSvc/%s:%d", server_name, connection->port) < 0) { free(auth->tds_auth.packet); sec_fn->FreeCredentialsHandle(&auth->cred); free(auth); return NULL; } tdsdump_log(TDS_DBG_NETWORK, "kerberos name %s\n", auth->sname); } status = sec_fn->InitializeSecurityContextA(&auth->cred, NULL, auth->sname, ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, 0, SECURITY_NETWORK_DREP, NULL, 0, &auth->cred_ctx, &desc, &attrs, &ts); if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) { sec_fn->CompleteAuthToken(&auth->cred_ctx, &desc); } else if(status != SEC_E_OK) { free(auth->sname); free(auth->tds_auth.packet); sec_fn->FreeCredentialsHandle(&auth->cred); free(auth); return NULL; } auth->tds_auth.packet_len = buf.cbBuffer; return &auth->tds_auth; }