2 Unix SMB/CIFS implementation.
4 Deal with unix elements in the security token
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "auth/auth.h"
25 #include "libcli/wbclient/wbclient.h"
26 #include "param/param.h"
29 #define DBGC_CLASS DBGC_AUTH
32 form a security_unix_token from the current security_token
34 NTSTATUS
security_token_to_unix_token(TALLOC_CTX
*mem_ctx
,
35 struct security_token
*token
,
36 struct security_unix_token
**sec
)
43 match
= security_token_is_system(token
);
46 * SYSTEM user uid and gid is 0
49 *sec
= talloc_zero(mem_ctx
, struct security_unix_token
);
51 return NT_STATUS_NO_MEMORY
;
57 /* we can't do unix security without a user and group */
58 if (token
->num_sids
< PRIMARY_SIDS_COUNT
) {
59 return NT_STATUS_ACCESS_DENIED
;
62 *sec
= talloc_zero(mem_ctx
, struct security_unix_token
);
64 return NT_STATUS_NO_MEMORY
;
67 ids
= talloc_zero_array(mem_ctx
, struct id_map
, token
->num_sids
);
68 NT_STATUS_HAVE_NO_MEMORY(ids
);
70 for (s
=0; s
< token
->num_sids
; s
++) {
71 ids
[s
].sid
= &token
->sids
[s
];
72 ids
[s
].status
= ID_UNKNOWN
;
75 status
= wbc_sids_to_xids(ids
, token
->num_sids
);
76 NT_STATUS_NOT_OK_RETURN(status
);
79 if (ids
[PRIMARY_USER_SID_INDEX
].xid
.type
!= ID_TYPE_BOTH
) {
83 (*sec
)->groups
= talloc_array(*sec
, gid_t
, (*sec
)->ngroups
);
84 NT_STATUS_HAVE_NO_MEMORY((*sec
)->groups
);
87 if (ids
[PRIMARY_USER_SID_INDEX
].xid
.type
== ID_TYPE_BOTH
) {
88 (*sec
)->uid
= ids
[0].xid
.id
;
89 (*sec
)->groups
[g
] = ids
[0].xid
.id
;
91 } else if (ids
[PRIMARY_USER_SID_INDEX
].xid
.type
== ID_TYPE_UID
) {
92 (*sec
)->uid
= ids
[0].xid
.id
;
94 struct dom_sid_buf buf
;
95 DEBUG(0, ("Unable to convert first SID (%s) in user token to a UID. Conversion was returned as type %d, full token:\n",
96 dom_sid_str_buf(ids
[PRIMARY_USER_SID_INDEX
].sid
, &buf
),
97 (int)ids
[PRIMARY_USER_SID_INDEX
].xid
.type
));
98 security_token_debug(DBGC_AUTH
, 0, token
);
99 return NT_STATUS_INVALID_SID
;
102 if (ids
[PRIMARY_GROUP_SID_INDEX
].xid
.type
== ID_TYPE_BOTH
||
103 ids
[PRIMARY_GROUP_SID_INDEX
].xid
.type
== ID_TYPE_GID
) {
104 (*sec
)->gid
= ids
[PRIMARY_GROUP_SID_INDEX
].xid
.id
;
105 (*sec
)->groups
[g
] = ids
[PRIMARY_GROUP_SID_INDEX
].xid
.id
;
108 struct dom_sid_buf buf
;
109 DEBUG(0, ("Unable to convert second SID (%s) in user token to a GID. Conversion was returned as type %d, full token:\n",
110 dom_sid_str_buf(ids
[PRIMARY_GROUP_SID_INDEX
].sid
, &buf
),
111 (int)ids
[PRIMARY_GROUP_SID_INDEX
].xid
.type
));
112 security_token_debug(DBGC_AUTH
, 0, token
);
113 return NT_STATUS_INVALID_SID
;
116 for (s
=REMAINING_SIDS_INDEX
; s
< token
->num_sids
; s
++) {
117 if (ids
[s
].xid
.type
== ID_TYPE_BOTH
||
118 ids
[s
].xid
.type
== ID_TYPE_GID
) {
119 (*sec
)->groups
[g
] = ids
[s
].xid
.id
;
122 struct dom_sid_buf buf
;
123 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",
124 dom_sid_str_buf(ids
[s
].sid
, &buf
),
125 (unsigned int)s
, (int)ids
[s
].xid
.type
));
126 security_token_debug(DBGC_AUTH
, 0, token
);
127 return NT_STATUS_INVALID_SID
;
131 DEBUG(5, ("Successfully converted security token to a unix token:"));
132 security_token_debug(0, 5, token
);
139 * Fill in the unix_info elements in a struct session_info
141 NTSTATUS
fill_unix_info(struct loadparm_context
*lp_ctx
,
142 const char *original_user_name
,
143 struct auth_session_info
*session_info
)
145 session_info
->unix_info
= talloc_zero(session_info
,
146 struct auth_user_info_unix
);
147 NT_STATUS_HAVE_NO_MEMORY(session_info
->unix_info
);
149 session_info
->unix_info
->unix_name
=
150 talloc_asprintf(session_info
->unix_info
,
151 "%s%s%s", session_info
->info
->domain_name
,
152 lpcfg_winbind_separator(lp_ctx
),
153 session_info
->info
->account_name
);
154 NT_STATUS_HAVE_NO_MEMORY(session_info
->unix_info
->unix_name
);
156 if (original_user_name
== NULL
) {
157 original_user_name
= session_info
->unix_info
->unix_name
;
160 session_info
->unix_info
->sanitized_username
=
161 talloc_alpha_strcpy(session_info
->unix_info
,
164 NT_STATUS_HAVE_NO_MEMORY(session_info
->unix_info
->sanitized_username
);
170 Fill in the auth_user_info_unix and auth_unix_token elements in a struct session_info
172 NTSTATUS
auth_session_info_fill_unix(struct loadparm_context
*lp_ctx
,
173 const char *original_user_name
,
174 struct auth_session_info
*session_info
)
176 NTSTATUS status
= NT_STATUS_OK
;
178 status
= security_token_to_unix_token(session_info
,
179 session_info
->security_token
,
180 &session_info
->unix_token
);
181 if (!NT_STATUS_IS_OK(status
)) {
185 status
= fill_unix_info(lp_ctx
,
188 if (!NT_STATUS_IS_OK(status
)) {
196 * Set the given auth_user_info_unix and auth_unix_token elements in a
197 * struct session_info, similar auth_session_info_fill_unix().
198 * Receives the uid and gid for the unix token as parameters and does
199 * not query the unix token from winbind (via security_token_to_unix_token()).
200 * This is useful to fill a user session info manually if winbind is not
203 NTSTATUS
auth_session_info_set_unix(struct loadparm_context
*lp_ctx
,
204 const char *original_user_name
,
207 struct auth_session_info
*session_info
)
211 session_info
->unix_token
= talloc_zero(session_info
,
212 struct security_unix_token
);
213 if (session_info
->unix_token
== NULL
) {
214 return NT_STATUS_NO_MEMORY
;
217 session_info
->unix_token
->uid
= uid
;
218 session_info
->unix_token
->gid
= gid
;
220 status
= fill_unix_info(lp_ctx
,
223 if (!NT_STATUS_IS_OK(status
)) {