r9792: Rename StrCaseCmp -> strcasecmp_m. All these years I was thinking
[nivanova/samba-autobuild/.git] / source4 / libnet / libnet_samdump.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Extract the user/system database from a remote SamSync server
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
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
24 #include "includes.h"
25 #include "libnet/libnet.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "librpc/gen_ndr/ndr_samr.h"
28 #include "dlinklist.h"
29
30
31 struct samdump_secret {
32         struct samdump_secret *prev, *next;
33         DATA_BLOB secret;
34         char *name;
35         NTTIME mtime;
36 };
37
38 struct samdump_trusted_domain {
39         struct samdump_trusted_domain *prev, *next;
40         struct dom_sid *sid;
41         char *name;
42 };
43
44 struct samdump_state {
45         struct samdump_secret *secrets;
46         struct samdump_trusted_domain *trusted_domains;
47 };
48
49 static NTSTATUS vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
50                                             struct creds_CredentialState *creds,
51                                             struct netr_DELTA_ENUM *delta) 
52 {
53         uint32_t rid = delta->delta_id_union.rid;
54         struct netr_DELTA_USER *user = delta->delta_union.user;
55         const char *username = user->account_name.string;
56         char *hex_lm_password;
57         char *hex_nt_password;
58
59         hex_lm_password = smbpasswd_sethexpwd(mem_ctx, 
60                                               user->lm_password_present ? &user->lmpassword : NULL, 
61                                               user->acct_flags);
62         hex_nt_password = smbpasswd_sethexpwd(mem_ctx, 
63                                               user->nt_password_present ? &user->ntpassword : NULL, 
64                                               user->acct_flags);
65
66         printf("%s:%d:%s:%s:%s:LCT-%08X\n", username,
67                rid, hex_lm_password, hex_nt_password,
68                smbpasswd_encode_acb_info(mem_ctx, user->acct_flags),
69                (unsigned int)nt_time_to_unix(user->last_password_change));
70
71         return NT_STATUS_OK;
72 }
73
74 static NTSTATUS vampire_samdump_handle_secret(TALLOC_CTX *mem_ctx,
75                                               struct samdump_state *samdump_state,
76                                               struct creds_CredentialState *creds,
77                                               struct netr_DELTA_ENUM *delta) 
78 {
79         struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
80         const char *name = delta->delta_id_union.name;
81         struct samdump_secret *new = talloc(samdump_state, struct samdump_secret);
82
83         new->name = talloc_steal(new, name);
84         new->secret = data_blob_talloc(new, secret->current_cipher.cipher_data, secret->current_cipher.maxlen);
85         new->mtime = secret->current_cipher_set_time;
86
87         DLIST_ADD(samdump_state->secrets, new);
88
89         return NT_STATUS_OK;
90 }
91
92 static NTSTATUS vampire_samdump_handle_trusted_domain(TALLOC_CTX *mem_ctx,
93                                               struct samdump_state *samdump_state,
94                                               struct creds_CredentialState *creds,
95                                               struct netr_DELTA_ENUM *delta) 
96 {
97         struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain;
98         struct dom_sid *dom_sid = delta->delta_id_union.sid;
99
100         struct samdump_trusted_domain *new = talloc(samdump_state, struct samdump_trusted_domain);
101
102         new->name = talloc_steal(new, trusted_domain->domain_name.string);
103         new->sid = talloc_steal(new, dom_sid);
104
105         DLIST_ADD(samdump_state->trusted_domains, new);
106
107         return NT_STATUS_OK;
108 }
109
110 static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx,          
111                                   void *private,                        
112                                   struct creds_CredentialState *creds,
113                                   enum netr_SamDatabaseID database,
114                                   struct netr_DELTA_ENUM *delta,
115                                   char **error_string)
116 {
117         NTSTATUS nt_status = NT_STATUS_OK;
118         struct samdump_state *samdump_state = private;
119
120         *error_string = NULL;
121         switch (delta->delta_type) {
122         case NETR_DELTA_USER:
123         {
124                 /* not interested in builtin users */
125                 if (database == SAM_DATABASE_DOMAIN) {
126                         nt_status = vampire_samdump_handle_user(mem_ctx, 
127                                                                 creds,
128                                                                 delta);
129                         break;
130                 }
131         }
132         case NETR_DELTA_SECRET:
133         {
134                 nt_status = vampire_samdump_handle_secret(mem_ctx,
135                                                           samdump_state,
136                                                           creds,
137                                                           delta);
138                 break;
139         }
140         case NETR_DELTA_TRUSTED_DOMAIN:
141         {
142                 nt_status = vampire_samdump_handle_trusted_domain(mem_ctx,
143                                                                   samdump_state,
144                                                                   creds,
145                                                                   delta);
146                 break;
147         }
148         default:
149                 /* Can't dump them all right now */
150                 break;
151         }
152         return nt_status;
153 }
154
155 static NTSTATUS libnet_SamDump_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump *r)
156 {
157         NTSTATUS nt_status;
158         struct libnet_SamSync r2;
159         struct samdump_state *samdump_state = talloc(mem_ctx, struct samdump_state);
160
161         struct samdump_trusted_domain *t;
162         struct samdump_secret *s;
163
164         if (!samdump_state) {
165                 return NT_STATUS_NO_MEMORY;
166         }
167
168         samdump_state->secrets = NULL;
169         samdump_state->trusted_domains = NULL;
170
171         r2.error_string = NULL;
172         r2.delta_fn = libnet_samdump_fn;
173         r2.fn_ctx = samdump_state;
174         r2.machine_account = NULL; /* TODO:  Create a machine account, fill this in, and the delete it */
175         nt_status = libnet_SamSync_netlogon(ctx, samdump_state, &r2);
176         r->error_string = r2.error_string;
177
178         if (!NT_STATUS_IS_OK(nt_status)) {
179                 talloc_free(samdump_state);
180                 return nt_status;
181         }
182
183         printf("Trusted domains, sids and secrets:\n");
184         for (t=samdump_state->trusted_domains; t; t=t->next) {
185                 char *secret_name = talloc_asprintf(mem_ctx, "G$$%s", t->name);
186                 for (s=samdump_state->secrets; s; s=s->next) {
187                         if (strcasecmp_m(s->name, secret_name) == 0) {
188                                 char *secret_string;
189                                 if (convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, 
190                                                           s->secret.data, s->secret.length, 
191                                                           (void **)&secret_string) == -1) {
192                                         r->error_string = talloc_asprintf(mem_ctx, 
193                                                                           "Could not convert secret for domain %s to a string\n",
194                                                                           t->name);
195                                         talloc_free(samdump_state);
196                                         return NT_STATUS_INVALID_PARAMETER;
197                                 }
198                                 printf("%s\t%s\t%s\n", 
199                                        t->name, dom_sid_string(mem_ctx, t->sid), 
200                                        secret_string);
201                         }
202                 }
203         }
204         talloc_free(samdump_state);
205         return nt_status;
206 }
207
208
209
210 static NTSTATUS libnet_SamDump_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump *r)
211 {
212         NTSTATUS nt_status;
213         struct libnet_SamDump r2;
214         r2.level = LIBNET_SAMDUMP_NETLOGON;
215         r2.error_string = NULL;
216         nt_status = libnet_SamDump(ctx, mem_ctx, &r2);
217         r->error_string = r2.error_string;
218         
219         return nt_status;
220 }
221
222 NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump *r)
223 {
224         switch (r->level) {
225         case LIBNET_SAMDUMP_GENERIC:
226                 return libnet_SamDump_generic(ctx, mem_ctx, r);
227         case LIBNET_SAMDUMP_NETLOGON:
228                 return libnet_SamDump_netlogon(ctx, mem_ctx, r);
229         }
230
231         return NT_STATUS_INVALID_LEVEL;
232 }