*id_to_*id call reshape to return NTSTATUS errors
[ira/wip.git] / source3 / auth / auth_rhosts.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_AUTH
25
26 /****************************************************************************
27  Read the a hosts.equiv or .rhosts file and check if it
28  allows this user from this machine.
29 ****************************************************************************/
30
31 static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file)
32 {
33   int plus_allowed = 1;
34   char *file_host;
35   char *file_user;
36   char **lines = file_lines_load(equiv_file, NULL);
37   int i;
38
39   DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
40   if (! lines) return False;
41   for (i=0; lines[i]; i++) {
42     char *buf = lines[i];
43     trim_string(buf," "," ");
44
45     if (buf[0] != '#' && buf[0] != '\n') 
46     {
47       BOOL is_group = False;
48       int plus = 1;
49       char *bp = buf;
50       if (strcmp(buf, "NO_PLUS\n") == 0)
51       {
52         DEBUG(6, ("check_user_equiv NO_PLUS\n"));
53         plus_allowed = 0;
54       }
55       else {
56         if (buf[0] == '+') 
57         {
58           bp++;
59           if (*bp == '\n' && plus_allowed) 
60           {
61             /* a bare plus means everbody allowed */
62             DEBUG(6, ("check_user_equiv everybody allowed\n"));
63             file_lines_free(lines);
64             return True;
65           }
66         }
67         else if (buf[0] == '-')
68         {
69           bp++;
70           plus = 0;
71         }
72         if (*bp == '@') 
73         {
74           is_group = True;
75           bp++;
76         }
77         file_host = strtok(bp, " \t\n");
78         file_user = strtok(NULL, " \t\n");
79         DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", 
80                  file_user ? file_user : "(null)" ));
81         if (file_host && *file_host) 
82         {
83           BOOL host_ok = False;
84
85 #if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN)
86           if (is_group)
87             {
88               static char *mydomain = NULL;
89               if (!mydomain)
90                 yp_get_default_domain(&mydomain);
91               if (mydomain && innetgr(file_host,remote,user,mydomain))
92                 host_ok = True;
93             }
94 #else
95           if (is_group)
96             {
97               DEBUG(1,("Netgroups not configured\n"));
98               continue;
99             }
100 #endif
101
102           /* is it this host */
103           /* the fact that remote has come from a call of gethostbyaddr
104            * means that it may have the fully qualified domain name
105            * so we could look up the file version to get it into
106            * a canonical form, but I would rather just type it
107            * in full in the equiv file
108            */
109           if (!host_ok && !is_group && strequal(remote, file_host))
110             host_ok = True;
111
112           if (!host_ok)
113             continue;
114
115           /* is it this user */
116           if (file_user == 0 || strequal(user, file_user)) 
117             {
118               DEBUG(5, ("check_user_equiv matched %s%s %s\n",
119                         (plus ? "+" : "-"), file_host,
120                         (file_user ? file_user : "")));
121               file_lines_free(lines);
122               return (plus ? True : False);
123             }
124         }
125       }
126     }
127   }
128   file_lines_free(lines);
129   return False;
130 }
131
132 /****************************************************************************
133 check for a possible hosts equiv or rhosts entry for the user
134 ****************************************************************************/
135
136 static BOOL check_hosts_equiv(SAM_ACCOUNT *account)
137 {
138         uid_t uid;
139         char *fname = NULL;
140
141         fname = lp_hosts_equiv();
142         if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(account), &uid)))
143                 return False;
144
145         /* note: don't allow hosts.equiv on root */
146         if (fname && *fname && uid != 0) {
147                 if (check_user_equiv(pdb_get_username(account),client_name(),fname))
148                         return True;
149         }
150   
151         return False;
152 }
153
154
155 /****************************************************************************
156  Check for a valid .rhosts/hosts.equiv entry for this user
157 ****************************************************************************/
158
159 static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_context,
160                                           void *my_private_data, 
161                                           TALLOC_CTX *mem_ctx,
162                                           const auth_usersupplied_info *user_info, 
163                                           auth_serversupplied_info **server_info)
164 {
165         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
166         SAM_ACCOUNT *account = NULL;
167         if (!NT_STATUS_IS_OK(nt_status = 
168                              auth_get_sam_account(user_info->internal_username.str, 
169                                                   &account))) {
170                 return nt_status;
171         }
172
173         if (check_hosts_equiv(account)) {
174                 nt_status = make_server_info_sam(server_info, account);
175         } else {
176                 pdb_free_sam(&account);
177                 nt_status = NT_STATUS_LOGON_FAILURE;
178         }
179
180         return nt_status;
181 }
182
183 /* module initialisation */
184 NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
185 {
186         if (!make_auth_methods(auth_context, auth_method)) {
187                 return NT_STATUS_NO_MEMORY;
188         }
189
190         (*auth_method)->auth = check_hostsequiv_security;
191         (*auth_method)->name = "hostsequiv";
192         return NT_STATUS_OK;
193 }
194
195
196 /****************************************************************************
197  Check for a valid .rhosts/hosts.equiv entry for this user
198 ****************************************************************************/
199
200 static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
201                                       void *my_private_data, 
202                                       TALLOC_CTX *mem_ctx,
203                                       const auth_usersupplied_info *user_info, 
204                                       auth_serversupplied_info **server_info)
205 {
206         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
207         SAM_ACCOUNT *account = NULL;
208         pstring rhostsfile;
209         const char *home;
210         
211         if (!NT_STATUS_IS_OK(nt_status = 
212                              auth_get_sam_account(user_info->internal_username.str, 
213                                                   &account))) {
214                 return nt_status;
215         }
216
217         home = pdb_get_unix_homedir(account);
218
219         if (home) {
220                 slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
221                 become_root();
222                 if (check_user_equiv(pdb_get_username(account),client_name(),rhostsfile)) {
223                         nt_status = make_server_info_sam(server_info, account);
224                 } else {
225                         pdb_free_sam(&account);
226                         nt_status = NT_STATUS_LOGON_FAILURE;
227                 }
228                 unbecome_root();
229         } else {
230                 pdb_free_sam(&account);
231                 nt_status = NT_STATUS_LOGON_FAILURE;
232         }
233         
234         return nt_status;
235 }
236
237 /* module initialisation */
238 NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
239 {
240         if (!make_auth_methods(auth_context, auth_method)) {
241                 return NT_STATUS_NO_MEMORY;
242         }
243
244         (*auth_method)->auth = check_rhosts_security;
245         (*auth_method)->name = "rhosts";
246         return NT_STATUS_OK;
247 }
248
249 NTSTATUS auth_rhosts_init(void)
250 {
251         smb_register_auth(AUTH_INTERFACE_VERSION, "rhosts", auth_init_rhosts);
252         smb_register_auth(AUTH_INTERFACE_VERSION, "hostsequiv", auth_init_hostsequiv);
253         return NT_STATUS_OK;
254 }