r13346: use private proto header files for the torture tests
[ddiss/samba.git] / source4 / torture / rpc / schannel.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for schannel operations
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_netlogon.h"
25 #include "torture/rpc/proto.h"
26
27 #define TEST_MACHINE_NAME "schannel"
28
29 /*
30   do some samr ops using the schannel connection
31  */
32 static BOOL test_samr_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
33 {
34         NTSTATUS status;
35         struct samr_GetDomPwInfo r;
36         struct samr_Connect connect;
37         struct samr_OpenDomain opendom;
38         int i;
39         struct lsa_String name;
40         struct policy_handle handle;
41         struct policy_handle domain_handle;
42
43         name.string = lp_workgroup();
44         r.in.domain_name = &name;
45
46         connect.in.system_name = 0;
47         connect.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
48         connect.out.connect_handle = &handle;
49         
50         printf("Testing Connect and OpenDomain on BUILTIN\n");
51
52         status = dcerpc_samr_Connect(p, mem_ctx, &connect);
53         if (!NT_STATUS_IS_OK(status)) {
54                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
55                         printf("Connect failed (expected, schannel mapped to anonymous): %s\n",
56                                nt_errstr(status));
57                 } else {
58                         printf("Connect failed - %s\n", nt_errstr(status));
59                         return False;
60                 }
61         } else {
62                 opendom.in.connect_handle = &handle;
63                 opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
64                 opendom.in.sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
65                 opendom.out.domain_handle = &domain_handle;
66                 
67                 status = dcerpc_samr_OpenDomain(p, mem_ctx, &opendom);
68                 if (!NT_STATUS_IS_OK(status)) {
69                         printf("OpenDomain failed - %s\n", nt_errstr(status));
70                         return False;
71                 }
72         }
73
74         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
75         
76         /* do several ops to test credential chaining */
77         for (i=0;i<5;i++) {
78                 status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
79                 if (!NT_STATUS_IS_OK(status)) {
80                         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
81                                 printf("GetDomPwInfo op %d failed - %s\n", i, nt_errstr(status));
82                                 return False;
83                         }
84                 }
85         }
86
87         return True;
88 }
89
90
91 /*
92   do some lsa ops using the schannel connection
93  */
94 static BOOL test_lsa_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
95 {
96         struct lsa_GetUserName r;
97         NTSTATUS status;
98         BOOL ret = True;
99         struct lsa_StringPointer authority_name_p;
100
101         printf("\nTesting GetUserName\n");
102
103         r.in.system_name = "\\";        
104         r.in.account_name = NULL;       
105         r.in.authority_name = &authority_name_p;
106         authority_name_p.string = NULL;
107
108         /* do several ops to test credential chaining and various operations */
109         status = dcerpc_lsa_GetUserName(p, mem_ctx, &r);
110         
111         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
112                 printf("not considering %s to be an error\n", nt_errstr(status));
113         } else if (!NT_STATUS_IS_OK(status)) {
114                 printf("GetUserName failed - %s\n", nt_errstr(status));
115                 return False;
116         } else {
117                 if (!r.out.account_name) {
118                         return False;
119                 }
120                 
121                 if (strcmp(r.out.account_name->string, "ANONYMOUS LOGON") != 0) {
122                         printf("GetUserName returned wrong user: %s, expected %s\n",
123                                r.out.account_name->string, "ANONYMOUS LOGON");
124                         return False;
125                 }
126                 if (!r.out.authority_name || !r.out.authority_name->string) {
127                         return False;
128                 }
129                 
130                 if (strcmp(r.out.authority_name->string->string, "NT AUTHORITY") != 0) {
131                         printf("GetUserName returned wrong user: %s, expected %s\n",
132                                r.out.authority_name->string->string, "NT AUTHORITY");
133                         return False;
134                 }
135         }
136         if (!test_many_LookupSids(p, mem_ctx, NULL)) {
137                 printf("LsaLookupSids3 failed!\n");
138                 return False;
139         }
140
141         return ret;
142 }
143
144
145 /*
146   test a schannel connection with the given flags
147  */
148 static BOOL test_schannel(TALLOC_CTX *mem_ctx, 
149                           uint16_t acct_flags, uint32_t dcerpc_flags,
150                           int i)
151 {
152         BOOL ret = True;
153
154         struct test_join *join_ctx;
155         NTSTATUS status;
156         const char *binding = lp_parm_string(-1, "torture", "binding");
157         struct dcerpc_binding *b;
158         struct dcerpc_pipe *p = NULL;
159         struct dcerpc_pipe *p_netlogon = NULL;
160         struct dcerpc_pipe *p_lsa = NULL;
161         struct creds_CredentialState *creds;
162         struct cli_credentials *credentials;
163
164         TALLOC_CTX *test_ctx = talloc_named(mem_ctx, 0, "test_schannel context");
165
166         join_ctx = torture_join_domain(talloc_asprintf(mem_ctx, "%s%d", TEST_MACHINE_NAME, i), 
167                                        acct_flags, &credentials);
168         if (!join_ctx) {
169                 printf("Failed to join domain with acct_flags=0x%x\n", acct_flags);
170                 talloc_free(test_ctx);
171                 return False;
172         }
173
174         status = dcerpc_parse_binding(test_ctx, binding, &b);
175         if (!NT_STATUS_IS_OK(status)) {
176                 printf("Bad binding string %s\n", binding);
177                 goto failed;
178         }
179
180         b->flags &= ~DCERPC_AUTH_OPTIONS;
181         b->flags |= dcerpc_flags;
182
183         status = dcerpc_pipe_connect_b(test_ctx, &p, b, &dcerpc_table_samr,
184                                        credentials, NULL);
185         if (!NT_STATUS_IS_OK(status)) {
186                 printf("Failed to connect with schannel: %s\n", nt_errstr(status));
187                 goto failed;
188         }
189
190         if (!test_samr_ops(p, test_ctx)) {
191                 printf("Failed to process schannel secured SAMR ops\n");
192                 ret = False;
193         }
194
195         /* Also test that when we connect to the netlogon pipe, that
196          * the credentials we setup on the first pipe are valid for
197          * the second */
198
199         /* Swap the binding details from SAMR to NETLOGON */
200         status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_netlogon, NULL);
201         if (!NT_STATUS_IS_OK(status)) {
202                 goto failed;
203         }
204
205         status = dcerpc_secondary_connection(p, &p_netlogon, 
206                                              b);
207
208         if (!NT_STATUS_IS_OK(status)) {
209                 goto failed;
210         }
211
212         status = dcerpc_bind_auth(p_netlogon, &dcerpc_table_netlogon,
213                                   credentials, DCERPC_AUTH_TYPE_SCHANNEL,
214                                   dcerpc_auth_level(p->conn),
215                                   NULL);
216
217         if (!NT_STATUS_IS_OK(status)) {
218                 goto failed;
219         }
220
221         status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, test_ctx, &creds);
222         if (!NT_STATUS_IS_OK(status)) {
223                 goto failed;
224         }
225
226         /* do a couple of logins */
227         if (!test_netlogon_ops(p_netlogon, test_ctx, credentials, creds)) {
228                 printf("Failed to process schannel secured NETLOGON ops\n");
229                 ret = False;
230         }
231
232         /* Swap the binding details from SAMR to LSARPC */
233         status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_lsarpc, NULL);
234         if (!NT_STATUS_IS_OK(status)) {
235                 goto failed;
236         }
237
238         status = dcerpc_secondary_connection(p, &p_lsa, 
239                                              b);
240
241         if (!NT_STATUS_IS_OK(status)) {
242                 goto failed;
243         }
244
245         status = dcerpc_bind_auth(p_lsa, &dcerpc_table_lsarpc,
246                                   credentials, DCERPC_AUTH_TYPE_SCHANNEL,
247                                   dcerpc_auth_level(p->conn),
248                                   NULL);
249
250         if (!NT_STATUS_IS_OK(status)) {
251                 goto failed;
252         }
253
254         if (!test_lsa_ops(p_lsa, test_ctx)) {
255                 printf("Failed to process schannel secured LSA ops\n");
256                 ret = False;
257         }
258
259         torture_leave_domain(join_ctx);
260         talloc_free(test_ctx);
261         return ret;
262
263 failed:
264         torture_leave_domain(join_ctx);
265         talloc_free(test_ctx);
266         return False;   
267 }
268
269 /*
270   a schannel test suite
271  */
272 BOOL torture_rpc_schannel(void)
273 {
274         TALLOC_CTX *mem_ctx;
275         BOOL ret = True;
276         struct {
277                 uint16_t acct_flags;
278                 uint32_t dcerpc_flags;
279         } tests[] = {
280                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN},
281                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL},
282                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128},
283                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 },
284                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN },
285                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL },
286                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128 },
287                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 }
288         };
289         int i;
290
291         mem_ctx = talloc_init("torture_rpc_schannel");
292
293         for (i=0;i<ARRAY_SIZE(tests);i++) {
294                 if (!test_schannel(mem_ctx, 
295                                    tests[i].acct_flags, tests[i].dcerpc_flags,
296                                    i)) {
297                         printf("Failed with acct_flags=0x%x dcerpc_flags=0x%x \n",
298                                tests[i].acct_flags, tests[i].dcerpc_flags);
299                         ret = False;
300                         break;
301                 }
302         }
303
304         talloc_free(mem_ctx);
305
306         return ret;
307 }