2cdcdcc1c38a5bd0895694db77dfca36f01eeb46
[idra/samba.git] / source3 / auth / user_krb5.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Simo Sorce 2010
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21
22 #undef DBGC_CLASS
23 #define DBGC_CLASS DBGC_AUTH
24
25 #ifdef HAVE_KRB5
26 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
27                                      const char *cli_name,
28                                      const char *princ_name,
29                                      struct PAC_LOGON_INFO *logon_info,
30                                      bool *is_mapped,
31                                      bool *mapped_to_guest,
32                                      char **ntuser,
33                                      char **ntdomain,
34                                      char **username,
35                                      struct passwd **_pw)
36 {
37         NTSTATUS status;
38         char *domain = NULL;
39         char *realm = NULL;
40         char *user = NULL;
41         char *p;
42         fstring fuser;
43         fstring unixuser;
44         struct passwd *pw = NULL;
45
46         DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
47
48         p = strchr_m(princ_name, '@');
49         if (!p) {
50                 DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
51                           princ_name));
52                 return NT_STATUS_LOGON_FAILURE;
53         }
54
55         user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
56         if (!user) {
57                 return NT_STATUS_NO_MEMORY;
58         }
59
60         realm = talloc_strdup(talloc_tos(), p + 1);
61         if (!realm) {
62                 return NT_STATUS_NO_MEMORY;
63         }
64
65         if (!strequal(realm, lp_realm())) {
66                 DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
67                 if (!lp_allow_trusted_domains()) {
68                         return NT_STATUS_LOGON_FAILURE;
69                 }
70         }
71
72         if (logon_info && logon_info->info3.base.domain.string) {
73                 domain = talloc_strdup(mem_ctx,
74                                         logon_info->info3.base.domain.string);
75                 if (!domain) {
76                         return NT_STATUS_NO_MEMORY;
77                 }
78                 DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
79         } else {
80
81                 /* If we have winbind running, we can (and must) shorten the
82                    username by using the short netbios name. Otherwise we will
83                    have inconsistent user names. With Kerberos, we get the
84                    fully qualified realm, with ntlmssp we get the short
85                    name. And even w2k3 does use ntlmssp if you for example
86                    connect to an ip address. */
87
88                 wbcErr wbc_status;
89                 struct wbcDomainInfo *info = NULL;
90
91                 DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
92                            realm));
93
94                 wbc_status = wbcDomainInfo(realm, &info);
95
96                 if (WBC_ERROR_IS_OK(wbc_status)) {
97                         domain = talloc_strdup(mem_ctx,
98                                                 info->short_name);
99                         wbcFreeMemory(info);
100                 } else {
101                         DEBUG(3, ("Could not find short name: %s\n",
102                                   wbcErrorString(wbc_status)));
103                         domain = talloc_strdup(mem_ctx, realm);
104                 }
105                 if (!domain) {
106                         return NT_STATUS_NO_MEMORY;
107                 }
108                 DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
109         }
110
111         /* We have to use fstring for this - map_username requires it. */
112         fstr_sprintf(fuser, "%s%c%s", domain, *lp_winbind_separator(), user);
113
114         *is_mapped = map_username(fuser);
115
116         pw = smb_getpwnam(mem_ctx, fuser, unixuser, true);
117         if (pw) {
118                 /* if a real user check pam account restrictions */
119                 /* only really perfomed if "obey pam restriction" is true */
120                 /* do this before an eventual mapping to guest occurs */
121                 status = smb_pam_accountcheck(pw->pw_name, cli_name);
122                 if (!NT_STATUS_IS_OK(status)) {
123                         DEBUG(1, ("PAM account restrictions prevent user "
124                                   "[%s] login\n", unixuser));
125                         return status;
126                 }
127         }
128         if (!pw) {
129
130                 /* this was originally the behavior of Samba 2.2, if a user
131                    did not have a local uid but has been authenticated, then
132                    map them to a guest account */
133
134                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
135                         *mapped_to_guest = true;
136                         fstrcpy(fuser, lp_guestaccount());
137                         pw = smb_getpwnam(mem_ctx, fuser, unixuser, true);
138                 }
139
140                 /* extra sanity check that the guest account is valid */
141                 if (!pw) {
142                         DEBUG(1, ("Username %s is invalid on this system\n",
143                                   fuser));
144                         return NT_STATUS_LOGON_FAILURE;
145                 }
146         }
147
148         *username = talloc_strdup(mem_ctx, unixuser);
149         if (!*username) {
150                 return NT_STATUS_NO_MEMORY;
151         }
152         *ntuser = user;
153         *ntdomain = domain;
154         *_pw = pw;
155
156         return NT_STATUS_OK;
157 }
158 #else /* HAVE_KRB5 */
159 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
160                                      const char *cli_name,
161                                      const char *princ_name,
162                                      struct PAC_LOGON_INFO *logon_info,
163                                      bool *is_mapped,
164                                      bool *mapped_to_guest,
165                                      char **ntuser,
166                                      char **ntdomain,
167                                      char **username,
168                                      struct passwd **_pw)
169 {
170         return NT_STATUS_NOT_IMPLEMENTED;
171 }
172 #endif /* HAVE_KRB5 */