summaryrefslogtreecommitdiffstats
path: root/source4/auth/unix_token.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth/unix_token.c')
-rw-r--r--source4/auth/unix_token.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/source4/auth/unix_token.c b/source4/auth/unix_token.c
new file mode 100644
index 0000000..97b8292
--- /dev/null
+++ b/source4/auth/unix_token.c
@@ -0,0 +1,228 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Deal with unix elements in the security token
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Andrew Bartlett 2011
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "auth/auth.h"
+#include "libcli/wbclient/wbclient.h"
+#include "param/param.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+/*
+ form a security_unix_token from the current security_token
+*/
+NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
+ struct security_token *token,
+ struct security_unix_token **sec)
+{
+ uint32_t s, g;
+ NTSTATUS status;
+ struct id_map *ids;
+ bool match;
+
+ match = security_token_is_system(token);
+ if (match) {
+ /*
+ * SYSTEM user uid and gid is 0
+ */
+
+ *sec = talloc_zero(mem_ctx, struct security_unix_token);
+ if (*sec == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+ }
+
+ /* we can't do unix security without a user and group */
+ if (token->num_sids < PRIMARY_SIDS_COUNT) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ *sec = talloc_zero(mem_ctx, struct security_unix_token);
+ if (*sec == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids);
+ NT_STATUS_HAVE_NO_MEMORY(ids);
+
+ for (s=0; s < token->num_sids; s++) {
+ ids[s].sid = &token->sids[s];
+ ids[s].status = ID_UNKNOWN;
+ }
+
+ status = wbc_sids_to_xids(ids, token->num_sids);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ g = token->num_sids;
+ if (ids[PRIMARY_USER_SID_INDEX].xid.type != ID_TYPE_BOTH) {
+ g--;
+ }
+ (*sec)->ngroups = g;
+ (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups);
+ NT_STATUS_HAVE_NO_MEMORY((*sec)->groups);
+
+ g=0;
+ if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_BOTH) {
+ (*sec)->uid = ids[0].xid.id;
+ (*sec)->groups[g] = ids[0].xid.id;
+ g++;
+ } else if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_UID) {
+ (*sec)->uid = ids[0].xid.id;
+ } else {
+ struct dom_sid_buf buf;
+ DEBUG(0, ("Unable to convert first SID (%s) in user token to a UID. Conversion was returned as type %d, full token:\n",
+ dom_sid_str_buf(ids[PRIMARY_USER_SID_INDEX].sid, &buf),
+ (int)ids[PRIMARY_USER_SID_INDEX].xid.type));
+ security_token_debug(DBGC_AUTH, 0, token);
+ return NT_STATUS_INVALID_SID;
+ }
+
+ if (ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_BOTH ||
+ ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_GID) {
+ (*sec)->gid = ids[PRIMARY_GROUP_SID_INDEX].xid.id;
+ (*sec)->groups[g] = ids[PRIMARY_GROUP_SID_INDEX].xid.id;
+ g++;
+ } else {
+ struct dom_sid_buf buf;
+ DEBUG(0, ("Unable to convert second SID (%s) in user token to a GID. Conversion was returned as type %d, full token:\n",
+ dom_sid_str_buf(ids[PRIMARY_GROUP_SID_INDEX].sid, &buf),
+ (int)ids[PRIMARY_GROUP_SID_INDEX].xid.type));
+ security_token_debug(DBGC_AUTH, 0, token);
+ return NT_STATUS_INVALID_SID;
+ }
+
+ for (s=REMAINING_SIDS_INDEX; s < token->num_sids; s++) {
+ if (ids[s].xid.type == ID_TYPE_BOTH ||
+ ids[s].xid.type == ID_TYPE_GID) {
+ (*sec)->groups[g] = ids[s].xid.id;
+ g++;
+ } else {
+ struct dom_sid_buf buf;
+ DEBUG(0, ("Unable to convert SID (%s) at index %u in user token to a GID. Conversion was returned as type %d, full token:\n",
+ dom_sid_str_buf(ids[s].sid, &buf),
+ (unsigned int)s, (int)ids[s].xid.type));
+ security_token_debug(DBGC_AUTH, 0, token);
+ return NT_STATUS_INVALID_SID;
+ }
+ }
+
+ DEBUG(5, ("Successfully converted security token to a unix token:"));
+ security_token_debug(0, 5, token);
+ TALLOC_FREE(ids);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ * Fill in the unix_info elements in a struct session_info
+ */
+NTSTATUS fill_unix_info(struct loadparm_context *lp_ctx,
+ const char *original_user_name,
+ struct auth_session_info *session_info)
+{
+ session_info->unix_info = talloc_zero(session_info,
+ struct auth_user_info_unix);
+ NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info);
+
+ session_info->unix_info->unix_name =
+ talloc_asprintf(session_info->unix_info,
+ "%s%s%s", session_info->info->domain_name,
+ lpcfg_winbind_separator(lp_ctx),
+ session_info->info->account_name);
+ NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->unix_name);
+
+ if (original_user_name == NULL) {
+ original_user_name = session_info->unix_info->unix_name;
+ }
+
+ session_info->unix_info->sanitized_username =
+ talloc_alpha_strcpy(session_info->unix_info,
+ original_user_name,
+ ". _-$");
+ NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->sanitized_username);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ Fill in the auth_user_info_unix and auth_unix_token elements in a struct session_info
+*/
+NTSTATUS auth_session_info_fill_unix(struct loadparm_context *lp_ctx,
+ const char *original_user_name,
+ struct auth_session_info *session_info)
+{
+ NTSTATUS status = NT_STATUS_OK;
+
+ status = security_token_to_unix_token(session_info,
+ session_info->security_token,
+ &session_info->unix_token);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = fill_unix_info(lp_ctx,
+ original_user_name,
+ session_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ * Set the given auth_user_info_unix and auth_unix_token elements in a
+ * struct session_info, similar auth_session_info_fill_unix().
+ * Receives the uid and gid for the unix token as parameters and does
+ * not query the unix token from winbind (via security_token_to_unix_token()).
+ * This is useful to fill a user session info manually if winbind is not
+ * available.
+ */
+NTSTATUS auth_session_info_set_unix(struct loadparm_context *lp_ctx,
+ const char *original_user_name,
+ int uid,
+ int gid,
+ struct auth_session_info *session_info)
+{
+ NTSTATUS status;
+
+ session_info->unix_token = talloc_zero(session_info,
+ struct security_unix_token);
+ if (session_info->unix_token == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ session_info->unix_token->uid = uid;
+ session_info->unix_token->gid = gid;
+
+ status = fill_unix_info(lp_ctx,
+ original_user_name,
+ session_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}