This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[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   char *fname = NULL;
139
140   fname = lp_hosts_equiv();
141
142   /* note: don't allow hosts.equiv on root */
143   if (IS_SAM_UNIX_USER(account) && fname && *fname && (pdb_get_uid(account) != 0)) {
144           if (check_user_equiv(pdb_get_username(account),client_name(),fname))
145                   return(True);
146   }
147   
148   return(False);
149 }
150
151
152 /****************************************************************************
153  Check for a valid .rhosts/hosts.equiv entry for this user
154 ****************************************************************************/
155
156 static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_context,
157                                           void *my_private_data, 
158                                           TALLOC_CTX *mem_ctx,
159                                           const auth_usersupplied_info *user_info, 
160                                           auth_serversupplied_info **server_info)
161 {
162         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
163         SAM_ACCOUNT *account = NULL;
164         if (!NT_STATUS_IS_OK(nt_status = 
165                              auth_get_sam_account(user_info->internal_username.str, 
166                                                   &account))) {
167                 return nt_status;
168         }
169
170         if (check_hosts_equiv(account)) {
171                 nt_status = make_server_info_sam(server_info, account);
172         } else {
173                 pdb_free_sam(&account);
174                 nt_status = NT_STATUS_LOGON_FAILURE;
175         }
176
177         return nt_status;
178 }
179
180 /* module initialisation */
181 NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
182 {
183         if (!make_auth_methods(auth_context, auth_method)) {
184                 return NT_STATUS_NO_MEMORY;
185         }
186
187         (*auth_method)->auth = check_hostsequiv_security;
188         (*auth_method)->name = "hostsequiv";
189         return NT_STATUS_OK;
190 }
191
192
193 /****************************************************************************
194  Check for a valid .rhosts/hosts.equiv entry for this user
195 ****************************************************************************/
196
197 static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
198                                       void *my_private_data, 
199                                       TALLOC_CTX *mem_ctx,
200                                       const auth_usersupplied_info *user_info, 
201                                       auth_serversupplied_info **server_info)
202 {
203         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
204         SAM_ACCOUNT *account = NULL;
205         pstring rhostsfile;
206         const char *home;
207         
208         if (!NT_STATUS_IS_OK(nt_status = 
209                              auth_get_sam_account(user_info->internal_username.str, 
210                                                   &account))) {
211                 return nt_status;
212         }
213
214         home = pdb_get_unix_homedir(account);
215
216         if (home) {
217                 slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
218                 become_root();
219                 if (check_user_equiv(pdb_get_username(account),client_name(),rhostsfile)) {
220                         nt_status = make_server_info_sam(server_info, account);
221                 } else {
222                         pdb_free_sam(&account);
223                         nt_status = NT_STATUS_LOGON_FAILURE;
224                 }
225                 unbecome_root();
226         } else {
227                 pdb_free_sam(&account);
228                 nt_status = NT_STATUS_LOGON_FAILURE;
229         }
230         
231         return nt_status;
232 }
233
234 /* module initialisation */
235 NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
236 {
237         if (!make_auth_methods(auth_context, auth_method)) {
238                 return NT_STATUS_NO_MEMORY;
239         }
240
241         (*auth_method)->auth = check_rhosts_security;
242         (*auth_method)->name = "rhosts";
243         return NT_STATUS_OK;
244 }
245
246 NTSTATUS auth_rhosts_init(void)
247 {
248         smb_register_auth(AUTH_INTERFACE_VERSION, "rhosts", auth_init_rhosts);
249         smb_register_auth(AUTH_INTERFACE_VERSION, "hostsequiv", auth_init_hostsequiv);
250         return NT_STATUS_OK;
251 }