We are not meant to touch the username, so use the pass->pw_name output rather
[kai/samba.git] / source3 / auth / auth_rhosts.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26
27 /****************************************************************************
28  Read the a hosts.equiv or .rhosts file and check if it
29  allows this user from this machine.
30 ****************************************************************************/
31
32 static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file)
33 {
34   int plus_allowed = 1;
35   char *file_host;
36   char *file_user;
37   char **lines = file_lines_load(equiv_file, NULL);
38   int i;
39
40   DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
41   if (! lines) return False;
42   for (i=0; lines[i]; i++) {
43     char *buf = lines[i];
44     trim_string(buf," "," ");
45
46     if (buf[0] != '#' && buf[0] != '\n') 
47     {
48       BOOL is_group = False;
49       int plus = 1;
50       char *bp = buf;
51       if (strcmp(buf, "NO_PLUS\n") == 0)
52       {
53         DEBUG(6, ("check_user_equiv NO_PLUS\n"));
54         plus_allowed = 0;
55       }
56       else {
57         if (buf[0] == '+') 
58         {
59           bp++;
60           if (*bp == '\n' && plus_allowed) 
61           {
62             /* a bare plus means everbody allowed */
63             DEBUG(6, ("check_user_equiv everybody allowed\n"));
64             file_lines_free(lines);
65             return True;
66           }
67         }
68         else if (buf[0] == '-')
69         {
70           bp++;
71           plus = 0;
72         }
73         if (*bp == '@') 
74         {
75           is_group = True;
76           bp++;
77         }
78         file_host = strtok(bp, " \t\n");
79         file_user = strtok(NULL, " \t\n");
80         DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", 
81                  file_user ? file_user : "(null)" ));
82         if (file_host && *file_host) 
83         {
84           BOOL host_ok = False;
85
86 #if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN)
87           if (is_group)
88             {
89               static char *mydomain = NULL;
90               if (!mydomain)
91                 yp_get_default_domain(&mydomain);
92               if (mydomain && innetgr(file_host,remote,user,mydomain))
93                 host_ok = True;
94             }
95 #else
96           if (is_group)
97             {
98               DEBUG(1,("Netgroups not configured\n"));
99               continue;
100             }
101 #endif
102
103           /* is it this host */
104           /* the fact that remote has come from a call of gethostbyaddr
105            * means that it may have the fully qualified domain name
106            * so we could look up the file version to get it into
107            * a canonical form, but I would rather just type it
108            * in full in the equiv file
109            */
110           if (!host_ok && !is_group && strequal(remote, file_host))
111             host_ok = True;
112
113           if (!host_ok)
114             continue;
115
116           /* is it this user */
117           if (file_user == 0 || strequal(user, file_user)) 
118             {
119               DEBUG(5, ("check_user_equiv matched %s%s %s\n",
120                         (plus ? "+" : "-"), file_host,
121                         (file_user ? file_user : "")));
122               file_lines_free(lines);
123               return (plus ? True : False);
124             }
125         }
126       }
127     }
128   }
129   file_lines_free(lines);
130   return False;
131 }
132
133
134 /****************************************************************************
135 check for a possible hosts equiv or rhosts entry for the user
136 ****************************************************************************/
137 static BOOL check_hosts_equiv(char *user) /* should be const... */
138 {
139   char *fname = NULL;
140   pstring rhostsfile;
141   struct passwd *pass = Get_Pwnam(user,False);
142
143   if (!pass) 
144     return(False);
145
146   fname = lp_hosts_equiv();
147
148   /* note: don't allow hosts.equiv on root */
149   if (fname && *fname && (pass->pw_uid != 0)) {
150           if (check_user_equiv(pass->pw_name,client_name(),fname))
151                   return(True);
152   }
153   
154   if (lp_use_rhosts())
155     {
156       char *home = pass->pw_dir;
157       if (home) {
158               slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
159               if (check_user_equiv(pass->pw_name,client_name(),rhostsfile))
160                       return(True);
161       }
162     }
163
164   return(False);
165 }
166
167 /****************************************************************************
168  Check for a valid .rhosts/hosts.equiv entry for this user
169 ****************************************************************************/
170
171 NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, 
172                              auth_serversupplied_info *server_info)
173 {
174         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
175
176         become_root();
177         if (check_hosts_equiv(user_info->unix_username.str)) {
178                 nt_status = NT_STATUS_OK;
179         }
180         unbecome_root();
181
182         return nt_status;
183 }
184
185
186