DATA_BLOB ticket;
char *client, *p, *domain;
fstring netbios_domain_name;
- const struct passwd *pw;
- char *user;
+ struct passwd *pw;
+ fstring user;
int sess_vuid;
NTSTATUS ret;
DATA_BLOB auth_data;
DATA_BLOB ap_rep, ap_rep_wrapped, response;
auth_serversupplied_info *server_info = NULL;
- DATA_BLOB session_key;
+ DATA_BLOB session_key = data_blob(NULL, 0);
uint8 tok_id[2];
- BOOL foreign = False;
DATA_BLOB nullblob = data_blob(NULL, 0);
+ fstring real_username;
+ BOOL map_domainuser_to_guest = False;
ZERO_STRUCT(ticket);
ZERO_STRUCT(auth_data);
if (!p) {
DEBUG(3,("Doesn't look like a valid principal\n"));
data_blob_free(&ap_rep);
+ data_blob_free(&session_key);
SAFE_FREE(client);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
if (!lp_allow_trusted_domains()) {
data_blob_free(&ap_rep);
+ data_blob_free(&session_key);
SAFE_FREE(client);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- foreign = True;
}
/* this gives a fully qualified user name (ie. with full realm).
fstrcpy(wb_request.domain_name, domain);
- wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
+ wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
&wb_request, &wb_response);
if (wb_result == NSS_STATUS_SUCCESS) {
}
}
- asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
-
- pw = smb_getpwnam( user );
+ fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
- SAFE_FREE(user);
- SAFE_FREE(client);
+ /* lookup the passwd struct, create a new user if necessary */
+
+ map_username( user );
+ pw = smb_getpwnam( user, real_username, True );
if (!pw) {
- DEBUG(1,("Username %s is invalid on this system\n",user));
- data_blob_free(&ap_rep);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+
+ /* this was originally the behavior of Samba 2.2, if a user
+ did not have a local uid but has been authenticated, then
+ map them to a guest account */
+
+ if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
+ map_domainuser_to_guest = True;
+ fstrcpy(user,lp_guestaccount());
+ pw = smb_getpwnam( user, real_username, True );
+ }
+
+ /* extra sanity check that the guest account is valid */
+
+ if ( !pw ) {
+ DEBUG(1,("Username %s is invalid on this system\n", user));
+ SAFE_FREE(client);
+ data_blob_free(&ap_rep);
+ data_blob_free(&session_key);
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
}
/* setup the string used by %U */
- sub_set_smb_name(pw->pw_name);
+ sub_set_smb_name( real_username );
reload_services(True);
-
- if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
- DEBUG(1,("make_server_info_from_pw failed!\n"));
- data_blob_free(&ap_rep);
- return ERROR_NT(ret);
+ if ( map_domainuser_to_guest ) {
+ make_server_info_guest(&server_info);
+ } else {
+ ret = make_server_info_pw(&server_info, real_username, pw);
+ if ( !NT_STATUS_IS_OK(ret) ) {
+ DEBUG(1,("make_server_info_from_pw failed!\n"));
+ SAFE_FREE(client);
+ data_blob_free(&ap_rep);
+ data_blob_free(&session_key);
+ passwd_free(&pw);
+ return ERROR_NT(ret);
+ }
}
+ passwd_free(&pw);
+
+ /* make_server_info_pw does not set the domain. Without this we end up
+ * with the local netbios name in substitutions for %D. */
+
+ if (server_info->sam_account != NULL) {
+ pdb_set_domain(server_info->sam_account, domain, PDB_SET);
+ }
/* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, session_key, nullblob, user);
+ /* register_vuid takes ownership of session_key, no need to free after this.
+ A better interface would copy it.... */
+ sess_vuid = register_vuid(server_info, session_key, nullblob, client);
- free(user);
+ SAFE_FREE(client);
if (sess_vuid == -1) {
ret = NT_STATUS_LOGON_FAILURE;
} else {
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
+
set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
SSVAL(outbuf, smb_uid, sess_vuid);
- if (!server_info->guest) {
+ if (!server_info->guest && !srv_signing_started()) {
/* We need to start the signing engine
* here but a W2K client sends the old
* "BSRSPYL " signature instead of the
* correct one. Subsequent packets will
* be correct.
*/
- srv_check_sign_mac(inbuf);
+ srv_check_sign_mac(inbuf, False);
}
}
nt_status = NT_STATUS_LOGON_FAILURE;
} else {
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
+
set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
SSVAL(outbuf,smb_uid,sess_vuid);
- if (!server_info->guest) {
+ if (!server_info->guest && !srv_signing_started()) {
/* We need to start the signing engine
* here but a W2K client sends the old
* "BSRSPYL " signature instead of the
* correct one. Subsequent packets will
* be correct.
*/
- srv_check_sign_mac(inbuf);
+
+ srv_check_sign_mac(inbuf, False);
}
}
}
DATA_BLOB secblob;
int i;
DATA_BLOB chal;
- BOOL got_kerberos = False;
+#ifdef HAVE_KRB5
+ BOOL got_kerberos_mechanism = False;
+#endif
NTSTATUS nt_status;
/* parse out the OIDs and the first sec blob */
server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
NTLMSSP mechtoken. --jerry */
-
+
+#ifdef HAVE_KRB5
if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
- got_kerberos = True;
+ got_kerberos_mechanism = True;
}
+#endif
for (i=0;OIDs[i];i++) {
DEBUG(3,("Got OID %s\n", OIDs[i]));
DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
#ifdef HAVE_KRB5
- if (got_kerberos && (SEC_ADS == lp_security())) {
+ if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
length, bufsize, &secblob);
data_blob_free(&secblob);
static BOOL done_sesssetup = False;
extern BOOL global_encrypted_passwords_negotiated;
extern BOOL global_spnego_negotiated;
- extern int Protocol;
+ extern enum protocol_types Protocol;
extern int max_send;
auth_usersupplied_info *user_info = NULL;
if (Protocol < PROTOCOL_NT1) {
uint16 passlen1 = SVAL(inbuf,smb_vwv7);
+
+ /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
+ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
+
if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
pstring pass;
BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
+#if 0
+ /* This was the previous fix. Not sure if it's still valid. JRA. */
if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
/* NT4.0 stuffs up plaintext unicode password lengths... */
srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
sizeof(pass), passlen1, STR_TERMINATE);
+#endif
+
+ if (unic && (passlen2 == 0) && passlen1) {
+ /* Only a ascii plaintext password was sent. */
+ srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
+ passlen1, STR_TERMINATE|STR_ASCII);
} else {
srvstr_pull(inbuf, pass, smb_buf(inbuf),
sizeof(pass), unic ? passlen2 : passlen1,
return ERROR_NT(nt_status_squash(nt_status));
}
- if (server_info->nt_session_key.data) {
- session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
- } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
- session_key = data_blob(NULL, 16);
- SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
- session_key.data);
+ if (server_info->user_session_key.data) {
+ session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
+ } else {
+ session_key = data_blob(NULL, 0);
}
- data_blob_free(&lm_resp);
data_blob_clear_free(&plaintext_password);
/* it's ok - setup a reply */
to a uid can get through without a password, on the same VC */
/* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
+ sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
if (sess_vuid == -1) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
+
+ if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
exit_server("reply_sesssetup_and_X: bad smb signature");
}