This is another rather major change to the samba authenticaion
[kai/samba.git] / source3 / nsswitch / winbindd_pam.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4
5    Winbind daemon - pam auth funcions
6
7    Copyright (C) Andrew Tridgell 2000
8    Copyright (C) Tim Potter 2001
9    Copyright (C) Andrew Bartlett 2001
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "winbindd.h"
27
28 /* Return a password structure from a username.  Specify whether cached data 
29    can be returned. */
30
31 enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) 
32 {
33         NTSTATUS result;
34         fstring name_domain, name_user;
35         int passlen;
36         unsigned char trust_passwd[16];
37         time_t last_change_time;
38         auth_usersupplied_info *user_info;
39         uint32 smb_uid_low;
40         NET_USER_INFO_3 info3;
41         NET_ID_INFO_CTR ctr;
42         struct cli_state *cli;
43         uchar chal[8];
44
45         DEBUG(3, ("[%5d]: pam auth %s\n", state->pid,
46                   state->request.data.auth.user));
47
48         /* Parse domain and username */
49
50         parse_domain_user(state->request.data.auth.user, name_domain, 
51                           name_user);
52
53         /* don't allow the null domain */
54
55         if (strcmp(name_domain,"") == 0) 
56                 return WINBINDD_ERROR;
57
58         passlen = strlen(state->request.data.auth.pass);
59                 
60         if (state->request.data.auth.pass[0])
61                 make_user_info_winbind(&user_info, 
62                                        name_user, name_domain,
63                                        state->request.data.auth.pass,
64                                        chal);
65         else
66                 return WINBINDD_ERROR;
67         
68         /*
69          * Get the machine account password for our primary domain
70          */
71
72         if (!secrets_fetch_trust_account_password(
73                 lp_workgroup(), trust_passwd, &last_change_time)) {
74                 DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
75                           "password for domain %s\n", lp_workgroup()));
76                 return WINBINDD_ERROR;
77         }
78
79         /* We really don't care what LUID we give the user. */
80
81         generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False);
82
83         ZERO_STRUCT(info3);
84
85         result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli);
86
87         if (!NT_STATUS_IS_OK(result)) {
88                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
89                 goto done;
90         }
91
92         result = cli_nt_login_network(cli, user_info, chal, smb_uid_low, 
93                                       &ctr, &info3);
94
95         free_user_info(&user_info);
96
97         cli_shutdown(cli);
98         
99  done:
100         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
101 }
102
103 /* Challenge Response Authentication Protocol */
104
105 enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) 
106 {
107         NTSTATUS result;
108         fstring name_domain, name_user;
109         unsigned char trust_passwd[16];
110         time_t last_change_time;
111
112         auth_usersupplied_info *user_info;
113         uint32 smb_uid_low;
114         NET_USER_INFO_3 info3;
115         NET_ID_INFO_CTR ctr;
116         struct cli_state *cli;
117
118         DEBUG(3, ("[%5d]: pam auth crap %s\n", state->pid,
119                   state->request.data.auth_crap.user));
120
121         /* Parse domain and username */
122
123         parse_domain_user(state->request.data.auth_crap.user, name_domain, 
124                           name_user);
125
126         make_user_info_winbind_crap(
127                 &user_info, name_user, 
128                 name_domain, 
129                 (uchar *)state->request.data.auth_crap.lm_resp,
130                 state->request.data.auth_crap.lm_resp_len,
131                 (uchar *)state->request.data.auth_crap.nt_resp,
132                 state->request.data.auth_crap.nt_resp_len);
133         
134         /*
135          * Get the machine account password for our primary domain
136          */
137
138         if (!secrets_fetch_trust_account_password(
139                 lp_workgroup(), trust_passwd, &last_change_time)) {
140                 DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
141                           "password for domain %s\n", lp_workgroup()));
142                 return WINBINDD_ERROR;
143         }
144
145         /* We really don't care what LUID we give the user. */
146
147         generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False);
148
149         ZERO_STRUCT(info3);
150
151         result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli);
152
153         if (!NT_STATUS_IS_OK(result)) {
154                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
155                 goto done;
156         }
157
158         result = cli_nt_login_network(cli, user_info, state->request.data.auth_crap.chal,
159                                       smb_uid_low, &ctr, &info3);
160
161         free_user_info(&user_info);
162
163         cli_shutdown(cli);
164
165  done:
166         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
167 }
168
169 /* Change a user password */
170
171 enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
172 {
173     char *oldpass, *newpass;
174     fstring domain, user;
175     uchar nt_oldhash[16];
176     uchar lm_oldhash[16];
177
178     DEBUG(3, ("[%5d]: pam chauthtok %s\n", state->pid,
179               state->request.data.chauthtok.user));
180
181     /* Setup crap */
182
183     if (state == NULL) return WINBINDD_ERROR;
184
185     parse_domain_user(state->request.data.chauthtok.user, domain, user);
186
187     oldpass = state->request.data.chauthtok.oldpass;
188     newpass = state->request.data.chauthtok.newpass;
189
190     nt_lm_owf_gen(oldpass, nt_oldhash, lm_oldhash);
191
192     /* Change password */
193
194 #if 0
195
196     /* XXX */
197
198     if (!msrpc_sam_ntchange_pwd(server_state.controller, domain, user,
199                                lm_oldhash, nt_oldhash, newpass)) {
200         DEBUG(0, ("password change failed for user %s/%s\n", domain, user));
201         return WINBINDD_ERROR;
202     }
203 #endif
204     
205     return WINBINDD_OK;
206 }