This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[samba.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 /****************************************************************************
24  Read the a hosts.equiv or .rhosts file and check if it
25  allows this user from this machine.
26 ****************************************************************************/
27
28 static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file)
29 {
30   int plus_allowed = 1;
31   char *file_host;
32   char *file_user;
33   char **lines = file_lines_load(equiv_file, NULL);
34   int i;
35
36   DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
37   if (! lines) return False;
38   for (i=0; lines[i]; i++) {
39     char *buf = lines[i];
40     trim_string(buf," "," ");
41
42     if (buf[0] != '#' && buf[0] != '\n') 
43     {
44       BOOL is_group = False;
45       int plus = 1;
46       char *bp = buf;
47       if (strcmp(buf, "NO_PLUS\n") == 0)
48       {
49         DEBUG(6, ("check_user_equiv NO_PLUS\n"));
50         plus_allowed = 0;
51       }
52       else {
53         if (buf[0] == '+') 
54         {
55           bp++;
56           if (*bp == '\n' && plus_allowed) 
57           {
58             /* a bare plus means everbody allowed */
59             DEBUG(6, ("check_user_equiv everybody allowed\n"));
60             file_lines_free(lines);
61             return True;
62           }
63         }
64         else if (buf[0] == '-')
65         {
66           bp++;
67           plus = 0;
68         }
69         if (*bp == '@') 
70         {
71           is_group = True;
72           bp++;
73         }
74         file_host = strtok(bp, " \t\n");
75         file_user = strtok(NULL, " \t\n");
76         DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", 
77                  file_user ? file_user : "(null)" ));
78         if (file_host && *file_host) 
79         {
80           BOOL host_ok = False;
81
82 #if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN)
83           if (is_group)
84             {
85               static char *mydomain = NULL;
86               if (!mydomain)
87                 yp_get_default_domain(&mydomain);
88               if (mydomain && innetgr(file_host,remote,user,mydomain))
89                 host_ok = True;
90             }
91 #else
92           if (is_group)
93             {
94               DEBUG(1,("Netgroups not configured\n"));
95               continue;
96             }
97 #endif
98
99           /* is it this host */
100           /* the fact that remote has come from a call of gethostbyaddr
101            * means that it may have the fully qualified domain name
102            * so we could look up the file version to get it into
103            * a canonical form, but I would rather just type it
104            * in full in the equiv file
105            */
106           if (!host_ok && !is_group && strequal(remote, file_host))
107             host_ok = True;
108
109           if (!host_ok)
110             continue;
111
112           /* is it this user */
113           if (file_user == 0 || strequal(user, file_user)) 
114             {
115               DEBUG(5, ("check_user_equiv matched %s%s %s\n",
116                         (plus ? "+" : "-"), file_host,
117                         (file_user ? file_user : "")));
118               file_lines_free(lines);
119               return (plus ? True : False);
120             }
121         }
122       }
123     }
124   }
125   file_lines_free(lines);
126   return False;
127 }
128
129
130 /****************************************************************************
131 check for a possible hosts equiv or rhosts entry for the user
132 ****************************************************************************/
133
134 static BOOL check_hosts_equiv(struct passwd *pass)
135 {
136   char *fname = NULL;
137
138   if (!pass) 
139     return(False);
140
141   fname = lp_hosts_equiv();
142
143   /* note: don't allow hosts.equiv on root */
144   if (fname && *fname && (pass->pw_uid != 0)) {
145           if (check_user_equiv(pass->pw_name,client_name(),fname))
146                   return(True);
147   }
148   
149   return(False);
150 }
151
152
153 /****************************************************************************
154  Check for a valid .rhosts/hosts.equiv entry for this user
155 ****************************************************************************/
156
157 static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_context,
158                                           void *my_private_data, 
159                                           TALLOC_CTX *mem_ctx,
160                                           const auth_usersupplied_info *user_info, 
161                                           auth_serversupplied_info **server_info)
162 {
163         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
164         struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
165         
166         if (pass) {
167                 if (check_hosts_equiv(pass)) {
168                         nt_status = NT_STATUS_OK;
169                         make_server_info_pw(server_info, pass);
170                 }
171         } else {
172                 nt_status = NT_STATUS_NO_SUCH_USER;
173         }
174
175         return nt_status;
176 }
177
178 /* module initialisation */
179 BOOL auth_init_hostsequiv(struct auth_context *auth_context, auth_methods **auth_method) 
180 {
181         if (!make_auth_methods(auth_context, auth_method)) {
182                 return False;
183         }
184
185         (*auth_method)->auth = check_hostsequiv_security;
186         return True;
187 }
188
189
190 /****************************************************************************
191  Check for a valid .rhosts/hosts.equiv entry for this user
192 ****************************************************************************/
193
194 static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
195                                       void *my_private_data, 
196                                       TALLOC_CTX *mem_ctx,
197                                       const auth_usersupplied_info *user_info, 
198                                       auth_serversupplied_info **server_info)
199 {
200         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
201         struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
202         pstring rhostsfile;
203         
204         if (pass) {
205                 char *home = pass->pw_dir;
206                 if (home) {
207                         slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
208                         become_root();
209                         if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) {
210                                 nt_status = NT_STATUS_OK;
211                                 make_server_info_pw(server_info, pass);
212                         }
213                         unbecome_root();
214                 } 
215         } else {
216                 nt_status = NT_STATUS_NO_SUCH_USER;
217         }
218
219         return nt_status;
220 }
221
222 /* module initialisation */
223 BOOL auth_init_rhosts(struct auth_context *auth_context, auth_methods **auth_method) 
224 {
225         if (!make_auth_methods(auth_context, auth_method)) {
226                 return False;
227         }
228
229         (*auth_method)->auth = check_rhosts_security;
230         return True;
231 }