From d7d8a5ed94a2b572b6818008a858f8c6b529dd03 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 15 Jul 2011 11:38:49 +1000 Subject: s3-auth Add struct auth3_session_info to aid transition to auth_session info This will allow a gradual conversion of the required elements from the current struct auth_serversupplied_info. This commit adds the structure definition and some helper functions to copy between the two structures. At this stage these structures and functions are IDENTICAL to the existing code, and so show the past history of that code. The plan is to slowly modify them over the course of the patch series, so that the changes being made a clear. By using a seperate structure to auth_serversupplied_info we can remove elements that are not needed after the authentication, and we can choose a layout that best reflects the needs of runtime users, rather than the internals of the authentication subsystem. By eventually using the auth_session_info from auth.idl, we will gain a single session authorization structure across the whole codebase, allowing more code to be shared, and a much more transparent process for forwarding authorization credentials over the named pipe proxy. Andrew Bartlett Signed-off-by: Andrew Tridgell --- source3/auth/auth_util.c | 180 +++++++++++++++++++++++++++++++++++++++++++++ source3/auth/proto.h | 3 + source3/auth/server_info.c | 34 +++++++++ source3/include/auth.h | 49 ++++++++++++ 4 files changed, 266 insertions(+) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 5553300ad1..a8c737dd88 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -34,6 +34,9 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH +static struct auth3_session_info *copy_serverinfo_session_info(TALLOC_CTX *mem_ctx, + const struct auth_serversupplied_info *src); + /**************************************************************************** Create a UNIX user on demand. ****************************************************************************/ @@ -965,6 +968,183 @@ struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx, return dst; } +static struct auth_serversupplied_info *copy_session_info_serverinfo(TALLOC_CTX *mem_ctx, + const struct auth3_session_info *src) +{ + struct auth_serversupplied_info *dst; + + dst = make_server_info(mem_ctx); + if (dst == NULL) { + return NULL; + } + + dst->guest = src->guest; + dst->system = src->system; + dst->utok.uid = src->utok.uid; + dst->utok.gid = src->utok.gid; + dst->utok.ngroups = src->utok.ngroups; + if (src->utok.ngroups != 0) { + dst->utok.groups = (gid_t *)talloc_memdup( + dst, src->utok.groups, + sizeof(gid_t)*dst->utok.ngroups); + } else { + dst->utok.groups = NULL; + } + + if (src->security_token) { + dst->security_token = dup_nt_token(dst, src->security_token); + if (!dst->security_token) { + TALLOC_FREE(dst); + return NULL; + } + } + + dst->session_key = data_blob_talloc( dst, src->session_key.data, + src->session_key.length); + + dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data, + src->lm_session_key.length); + + dst->info3 = copy_netr_SamInfo3(dst, src->info3); + if (!dst->info3) { + TALLOC_FREE(dst); + return NULL; + } + dst->extra = src->extra; + + dst->unix_name = talloc_strdup(dst, src->unix_name); + if (!dst->unix_name) { + TALLOC_FREE(dst); + return NULL; + } + + dst->sanitized_username = talloc_strdup(dst, src->sanitized_username); + if (!dst->sanitized_username) { + TALLOC_FREE(dst); + return NULL; + } + + return dst; +} + +static struct auth3_session_info *copy_serverinfo_session_info(TALLOC_CTX *mem_ctx, + const struct auth_serversupplied_info *src) +{ + struct auth3_session_info *dst; + + dst = make_auth3_session_info(mem_ctx); + if (dst == NULL) { + return NULL; + } + + dst->guest = src->guest; + dst->system = src->system; + dst->utok.uid = src->utok.uid; + dst->utok.gid = src->utok.gid; + dst->utok.ngroups = src->utok.ngroups; + if (src->utok.ngroups != 0) { + dst->utok.groups = (gid_t *)talloc_memdup( + dst, src->utok.groups, + sizeof(gid_t)*dst->utok.ngroups); + } else { + dst->utok.groups = NULL; + } + + if (src->security_token) { + dst->security_token = dup_nt_token(dst, src->security_token); + if (!dst->security_token) { + TALLOC_FREE(dst); + return NULL; + } + } + + dst->session_key = data_blob_talloc( dst, src->session_key.data, + src->session_key.length); + + dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data, + src->lm_session_key.length); + + dst->info3 = copy_netr_SamInfo3(dst, src->info3); + if (!dst->info3) { + TALLOC_FREE(dst); + return NULL; + } + dst->extra = src->extra; + + dst->unix_name = talloc_strdup(dst, src->unix_name); + if (!dst->unix_name) { + TALLOC_FREE(dst); + return NULL; + } + + dst->sanitized_username = talloc_strdup(dst, src->sanitized_username); + if (!dst->sanitized_username) { + TALLOC_FREE(dst); + return NULL; + } + + return dst; +} + +struct auth3_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + const struct auth3_session_info *src) +{ + struct auth3_session_info *dst; + + dst = make_auth3_session_info(mem_ctx); + if (dst == NULL) { + return NULL; + } + + dst->guest = src->guest; + dst->system = src->system; + dst->utok.uid = src->utok.uid; + dst->utok.gid = src->utok.gid; + dst->utok.ngroups = src->utok.ngroups; + if (src->utok.ngroups != 0) { + dst->utok.groups = (gid_t *)talloc_memdup( + dst, src->utok.groups, + sizeof(gid_t)*dst->utok.ngroups); + } else { + dst->utok.groups = NULL; + } + + if (src->security_token) { + dst->security_token = dup_nt_token(dst, src->security_token); + if (!dst->security_token) { + TALLOC_FREE(dst); + return NULL; + } + } + + dst->session_key = data_blob_talloc( dst, src->session_key.data, + src->session_key.length); + + dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data, + src->lm_session_key.length); + + dst->info3 = copy_netr_SamInfo3(dst, src->info3); + if (!dst->info3) { + TALLOC_FREE(dst); + return NULL; + } + dst->extra = src->extra; + + dst->unix_name = talloc_strdup(dst, src->unix_name); + if (!dst->unix_name) { + TALLOC_FREE(dst); + return NULL; + } + + dst->sanitized_username = talloc_strdup(dst, src->sanitized_username); + if (!dst->sanitized_username) { + TALLOC_FREE(dst); + return NULL; + } + + return dst; +} + /* * Set a new session key. Used in the rpc server where we have to override the * SMB level session key with SystemLibraryDTC diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 8ff9fa9b99..8bc2c6e458 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -168,6 +168,8 @@ NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **session_info); struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx, const struct auth_serversupplied_info *src); +struct auth3_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + const struct auth3_session_info *src); bool init_guest_info(void); NTSTATUS init_system_info(void); bool session_info_set_session_key(struct auth_serversupplied_info *info, @@ -223,6 +225,7 @@ struct netr_SamInfo3; struct netr_SamInfo6; struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx); +struct auth3_session_info *make_auth3_session_info(TALLOC_CTX *mem_ctx); NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info, uint8_t *pipe_session_key, size_t pipe_session_key_len, diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c index a53e556d28..12026060bd 100644 --- a/source3/auth/server_info.c +++ b/source3/auth/server_info.c @@ -63,6 +63,40 @@ struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx) return result; } +/* FIXME: do we really still need this ? */ +static int auth3_session_info_dtor(struct auth3_session_info *session_info) +{ + TALLOC_FREE(session_info->info3); + ZERO_STRUCTP(session_info); + return 0; +} + +/*************************************************************************** + Make a server_info struct. Free with TALLOC_FREE(). +***************************************************************************/ + +struct auth3_session_info *make_auth3_session_info(TALLOC_CTX *mem_ctx) +{ + struct auth3_session_info *result; + + result = talloc_zero(mem_ctx, struct auth3_session_info); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + talloc_set_destructor(result, auth3_session_info_dtor); + + /* Initialise the uid and gid values to something non-zero + which may save us from giving away root access if there + is a bug in allocating these fields. */ + + result->utok.uid = -1; + result->utok.gid = -1; + + return result; +} + /**************************************************************************** inits a netr_SamInfo2 structure from an auth_serversupplied_info. sam2 must already be initialized and is used as the talloc parent for its members. diff --git a/source3/include/auth.h b/source3/include/auth.h index 4f7cb9bb14..b1e5c32c36 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -75,6 +75,55 @@ struct auth_serversupplied_info { char *sanitized_username; }; +struct auth3_session_info { + bool guest; + bool system; + + struct security_unix_token utok; + + /* NT group information taken from the info3 structure */ + + struct security_token *security_token; + + /* This is the final session key, as used by SMB signing, and + * (truncated to 16 bytes) encryption on the SAMR and LSA pipes + * when over ncacn_np. + * It is calculated by NTLMSSP from the session key in the info3, + * and is set from the Kerberos session key using + * krb5_auth_con_getremotesubkey(). + * + * Bottom line, it is not the same as the session keys in info3. + */ + + DATA_BLOB session_key; + DATA_BLOB lm_session_key; + + struct netr_SamInfo3 *info3; + + /* this structure is filled *only* in pathological cases where the user + * sid or the primary group sid are not sids of the domain. Normally + * this happens only for unix accounts that have unix domain sids. + * This is checked only when info3.rid and/or info3.primary_gid are set + * to the special invalid value of 0xFFFFFFFF */ + struct extra_auth_info extra; + + /* + * This is a token from /etc/passwd and /etc/group + */ + bool nss_token; + + char *unix_name; + + /* + * For performance reasons we keep an alpha_strcpy-sanitized version + * of the username around as long as the global variable current_user + * still exists. If we did not do keep this, we'd have to call + * alpha_strcpy whenever we do a become_user(), potentially on every + * smb request. See set_current_user_info. + */ + char *sanitized_username; +}; + struct auth_context { DATA_BLOB challenge; -- cgit