25 RCSID(
"$Id: 4830fdc165af4b651b24ffb16ef4cc38db7ad38d $")
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/util/debug.h>
31 #include <core/ntstatus.h>
38 #ifndef WBC_MSV1_0_ALLOW_MSVCHAPV2
39 #define WBC_MSV1_0_ALLOW_MSVCHAPV2 0x00010000
55 char const *dom_name,
char const *
name)
57 struct wbcDomainSid sid;
58 enum wbcSidType name_type;
60 char *res_domain = NULL;
61 char *res_name = NULL;
65 err = wbcCtxLookupName(wb_ctx, dom_name,
name, &sid, &name_type);
66 if (!WBC_ERROR_IS_OK(
err))
return NULL;
69 err = wbcCtxLookupSid(wb_ctx, &sid, &res_domain, &res_name, &name_type);
70 if (!WBC_ERROR_IS_OK(
err))
return NULL;
72 MEM(res = talloc_strdup(ctx, res_name));
74 wbcFreeMemory(res_domain);
75 wbcFreeMemory(res_name);
98 struct wbcContext *wb_ctx = NULL;
99 struct wbcAuthUserParams authparams;
101 struct wbcAuthUserInfo *info = NULL;
102 struct wbcAuthErrorInfo *error = NULL;
110 memset(&authparams, 0,
sizeof(authparams));
113 authparams.domain_name = env_data->
wb_domain.vb_strvalue;
115 RWDEBUG2(
"No domain specified; authentication may fail because of this");
121 authparams.account_name = env_data->
wb_username.vb_strvalue;
126 authparams.level = WBC_AUTH_USER_LEVEL_RESPONSE;
127 authparams.password.response.nt_length =
NT_LENGTH;
130 authparams.password.response.nt_data = resp;
132 memcpy(authparams.password.response.challenge, challenge,
sizeof(authparams.password.response.challenge));
135 WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
136 WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
142 if (wb_ctx == NULL) {
143 RERROR(
"Unable to get winbind connection from pool");
147 RDEBUG2(
"Sending authentication request user \"%pV\" domain \"%pV\"",
150 err = wbcCtxAuthenticateUserEx(wb_ctx, &authparams, &info, &error);
151 if (
err == WBC_ERR_AUTH_ERROR &&
inst->wb_retry_with_normalised_username) {
155 char *normalised_username = NULL;
158 authparams.account_name);
159 if (!normalised_username)
goto release;
161 RDEBUG2(
"Starting retry, normalised username \"%pV\" -> \"%pV\"",
165 if (
talloc_memcmp_bstr(authparams.account_name, normalised_username) == 0)
goto release;
167 authparams.account_name = normalised_username;
173 RDEBUG2(
"Retrying authentication request user \"%pV\" domain \"%pV\"",
188 RERROR(
"Unable to get MS-CHAP2-Response");
193 vp_response->vp_octets + 2,
194 vp_challenge->vp_octets,
195 vp_chap_user_name->vp_strvalue, vp_chap_user_name->vp_length);
197 err = wbcCtxAuthenticateUserEx(wb_ctx, &authparams, &info, &error);
209 case WBC_ERR_SUCCESS:
211 RDEBUG2(
"Authenticated successfully");
216 case WBC_ERR_WINBIND_NOT_AVAILABLE:
217 RERROR(
"Unable to contact winbind!");
218 RDEBUG2(
"Check that winbind is running and that FreeRADIUS has");
219 RDEBUG2(
"permission to connect to the winbind privileged socket.");
222 case WBC_ERR_DOMAIN_NOT_FOUND:
226 case WBC_ERR_AUTH_ERROR:
235 if (error->nt_status == NT_STATUS_PASSWORD_EXPIRED ||
236 error->nt_status == NT_STATUS_PASSWORD_MUST_CHANGE) {
243 if (error->display_string) {
244 REDEBUG2(
"%s [0x%X]", error->display_string, error->nt_status);
246 REDEBUG2(
"Authentication failed [0x%X]", error->nt_status);
257 if (error && error->display_string) {
258 REDEBUG2(
"libwbclient error: wbcErr %d (%s)",
err, error->display_string);
266 if (info) wbcFreeMemory(info);
267 if (error) wbcFreeMemory(error);
#define WBC_MSV1_0_ALLOW_MSVCHAPV2
static char * wbclient_normalise_username(TALLOC_CTX *ctx, struct wbcContext *wb_ctx, char const *dom_name, char const *name)
Use Winbind to normalise a username.
int do_auth_wbclient(rlm_mschap_t const *inst, request_t *request, uint8_t const *challenge, uint8_t const *response, uint8_t nthashhash[NT_DIGEST_LENGTH], mschap_auth_call_env_t *env_data)
Check NTLM authentication direct to winbind via Samba's libwbclient library.
#define RWDEBUG2(fmt,...)
#define REDEBUG2(fmt,...)
@ FR_TYPE_STRING
String of printable characters.
void mschap_challenge_hash(uint8_t challenge[static MSCHAP_CHALLENGE_LENGTH], uint8_t const peer_challenge[static MSCHAP_PEER_CHALLENGE_LENGTH], uint8_t const auth_challenge[static MSCHAP_PEER_AUTHENTICATOR_CHALLENGE_LENGTH], char const *user_name, size_t user_name_len)
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
#define pair_update_request(_attr, _da)
static fr_dict_attr_t const * attr_ms_chap_user_name
fr_value_box_t wb_username
tmpl_t const * chap_challenge
tmpl_t const * chap2_response
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
Stores an attribute, a value and various bits of other data.
int talloc_memcmp_bstr(char const *a, char const *b)
Compares two talloced char arrays with memcmp.
#define fr_box_strvalue_buffer(_val)