s3:utils: let smbstatus report anonymous signing/encryption explicitly
[samba.git] / source4 / auth / unix_token.c
index 38109452a4bc8095ef527cfce02a774d5cc68909..97b8292a2dd1dc7d0ce328a2cfffadcad1861044 100644 (file)
 #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 wbc_context *wbc_ctx,
                                      struct security_token *token,
                                      struct security_unix_token **sec)
 {
        uint32_t s, g;
        NTSTATUS status;
        struct id_map *ids;
-       struct composite_context *ctx;
+       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 < 2) {
+       if (token->num_sids < PRIMARY_SIDS_COUNT) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
@@ -56,14 +72,11 @@ NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
                ids[s].status = ID_UNKNOWN;
        }
 
-       ctx = wbc_sids_to_xids_send(wbc_ctx, ids, token->num_sids, ids);
-       NT_STATUS_HAVE_NO_MEMORY(ctx);
-
-       status = wbc_sids_to_xids_recv(ctx, &ids);
+       status = wbc_sids_to_xids(ids, token->num_sids);
        NT_STATUS_NOT_OK_RETURN(status);
 
        g = token->num_sids;
-       if (ids[0].xid.type != ID_TYPE_BOTH) {
+       if (ids[PRIMARY_USER_SID_INDEX].xid.type != ID_TYPE_BOTH) {
                g--;
        }
        (*sec)->ngroups = g;
@@ -71,46 +84,46 @@ NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
        NT_STATUS_HAVE_NO_MEMORY((*sec)->groups);
 
        g=0;
-       if (ids[0].xid.type == ID_TYPE_BOTH) {
+       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[0].xid.type == ID_TYPE_UID) {
+       } else if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_UID) {
                (*sec)->uid = ids[0].xid.id;
        } else {
-               char *sid_str = dom_sid_string(mem_ctx, ids[0].sid);
+               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",
-                         sid_str, (int)ids[0].xid.type));
-               security_token_debug(0, 0, token);
-               talloc_free(sid_str);
+                         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[1].xid.type == ID_TYPE_BOTH ||
-           ids[1].xid.type == ID_TYPE_GID) {
-               (*sec)->gid = ids[1].xid.id;
-               (*sec)->groups[g] = ids[1].xid.id;
+       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 {
-               char *sid_str = dom_sid_string(mem_ctx, ids[1].sid);
+               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",
-                         sid_str, (int)ids[1].xid.type));
-               security_token_debug(0, 0, token);
-               talloc_free(sid_str);
+                         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=2; s < token->num_sids; s++) {
+       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 {
-                       char *sid_str = dom_sid_string(mem_ctx, ids[s].sid);
+                       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",
-                                 sid_str, (unsigned int)s, (int)ids[s].xid.type));
-                       security_token_debug(0, 0, token);
-                       talloc_free(sid_str);
+                                 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;
                }
        }
@@ -122,38 +135,94 @@ NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
        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 wbc_context *wbc_ctx,
-                                    struct loadparm_context *lp_ctx,
+NTSTATUS auth_session_info_fill_unix(struct loadparm_context *lp_ctx,
                                     const char *original_user_name,
                                     struct auth_session_info *session_info)
 {
-       char *su;
-       size_t len;
-       NTSTATUS status = security_token_to_unix_token(session_info, wbc_ctx,
-                                                      session_info->security_token,
-                                                      &session_info->unix_token);
+       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;
        }
 
-       session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
-       NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info);
+       status = fill_unix_info(lp_ctx,
+                               original_user_name,
+                               session_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       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);
+       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;
 
-       len = strlen(original_user_name) + 1;
-       session_info->unix_info->sanitized_username = su = talloc_array(session_info->unix_info, char, len);
-       NT_STATUS_HAVE_NO_MEMORY(su);
+       session_info->unix_token = talloc_zero(session_info,
+                                              struct security_unix_token);
+       if (session_info->unix_token == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       alpha_strcpy(su, original_user_name,
-                    ". _-$", len);
+       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;
 }