r9754: Upgrading with the command line utility now works, at least partially (-:
[kai/samba.git] / source4 / lib / samba3 / secrets.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Andrew Tridgell 1992-2001
4    Copyright (C) Andrew Bartlett      2002
5    Copyright (C) Rafal Szczesniak     2002
6    Copyright (C) Tim Potter           2001
7    Copyright (C) Jelmer Vernooij          2005
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /* the Samba secrets database stores any generated, private information
25    such as the local SID and machine trust password */
26
27 #include "includes.h"
28 #include "lib/tdb/include/tdb.h"
29 #include "lib/samba3/samba3.h"
30 #include "system/filesys.h"
31 #include "librpc/gen_ndr/ndr_security.h"
32 #include "lib/tdb/include/tdbutil.h"
33
34 /**
35  * Unpack SID into a pointer
36  *
37  * @param pack_buf pointer to buffer with packed representation
38  * @param bufsize size of the buffer
39  * @param sid pointer to sid structure to be filled with unpacked data
40  *
41  * @return size of structure unpacked from buffer
42  **/
43 static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, struct dom_sid* sid)
44 {
45         int idx, len = 0;
46         
47         if (!sid || !pack_buf) return -1;
48
49         len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb",
50                           &sid->sid_rev_num, &sid->num_auths);
51                           
52         for (idx = 0; idx < 6; idx++) {
53                 len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
54         }
55         
56         for (idx = 0; idx < 15; idx++) {
57                 len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
58         }
59         
60         return len;
61 }
62
63 static struct samba3_domainsecrets *secrets_find_domain(TALLOC_CTX *ctx, struct samba3_secrets *db, const char *key)
64 {
65         int i;
66
67         for (i = 0; i < db->domain_count; i++) 
68         {
69                 if (!StrCaseCmp(db->domains[i].name, key)) 
70                         return &db->domains[i];
71         }
72
73         db->domains = talloc_realloc(ctx, db->domains, struct samba3_domainsecrets, db->domain_count+1);
74         ZERO_STRUCT(db->domains[db->domain_count]);
75         db->domains[db->domain_count].name = talloc_strdup(db->domains, key); 
76
77         db->domain_count++;
78         
79         return &db->domains[db->domain_count-1];
80 }
81
82 static NTSTATUS ipc_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
83 {
84         cli_credentials_set_password(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED);
85         return NT_STATUS_OK;
86 }
87
88 static NTSTATUS ipc_username (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
89 {
90         cli_credentials_set_username(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED);
91         return NT_STATUS_OK;
92 }
93         
94 static NTSTATUS ipc_domain (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
95 {
96         cli_credentials_set_domain(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED);
97         return NT_STATUS_OK;
98 }
99
100 static NTSTATUS domain_sid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
101 {
102         struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
103         domainsec->sid.sub_auths = talloc_array(ctx, uint32_t, 15);
104         tdb_sid_unpack(tdb, vbuf.dptr, vbuf.dsize, &domainsec->sid);
105         return NT_STATUS_OK;
106 }
107
108 static NTSTATUS domain_guid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
109 {
110         struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
111         memcpy(&domainsec->guid, vbuf.dptr, vbuf.dsize);
112         return NT_STATUS_OK;
113 }
114
115 static NTSTATUS ldap_bind_pw (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
116 {
117         struct samba3_ldappw pw;
118         pw.dn = talloc_strdup(ctx, key);
119         pw.password = talloc_strdup(ctx, vbuf.dptr);
120
121         db->ldappws = talloc_realloc(ctx, db->ldappws, struct samba3_ldappw, db->ldappw_count+1);
122         db->ldappws[db->ldappw_count] = pw;
123         db->ldappw_count++;
124         return NT_STATUS_OK;
125 }
126
127 static NTSTATUS afs_keyfile (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
128 {
129         struct samba3_afs_keyfile keyfile;
130         memcpy(&keyfile, vbuf.dptr, vbuf.dsize);
131         keyfile.cell = talloc_strdup(ctx, key);
132
133         db->afs_keyfiles = talloc_realloc(ctx, db->afs_keyfiles, struct samba3_afs_keyfile, db->afs_keyfile_count+1);
134         db->afs_keyfiles[db->afs_keyfile_count] = keyfile;
135         db->afs_keyfile_count++;
136         
137         return NT_STATUS_OK;
138 }
139
140 static NTSTATUS machine_sec_channel_type (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
141 {
142         struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
143
144         domainsec->sec_channel_type = IVAL(vbuf.dptr, 0);
145         return NT_STATUS_OK;
146 }
147
148 static NTSTATUS machine_last_change_time (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
149 {
150         struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
151         domainsec->last_change_time = IVAL(vbuf.dptr, 0);
152         return NT_STATUS_OK;
153 }
154
155 static NTSTATUS machine_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
156 {
157         struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
158         domainsec->plaintext_pw = talloc_strdup(ctx, vbuf.dptr);
159         return NT_STATUS_OK;
160 }
161
162 static NTSTATUS machine_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
163 {
164         struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
165
166         memcpy(&domainsec->hash_pw, vbuf.dptr, vbuf.dsize);
167
168         return NT_STATUS_OK;
169 }
170
171 static NTSTATUS random_seed (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
172 {
173         /* Ignore */    
174         return NT_STATUS_OK;
175 }
176
177 static NTSTATUS domtrust_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) 
178 {
179         int idx, len = 0;
180         struct samba3_trusted_dom_pass pass;
181         int pass_len;
182         
183         if (!vbuf.dptr) 
184                 return NT_STATUS_UNSUCCESSFUL;
185
186         /* unpack unicode domain name and plaintext password */
187         len += tdb_unpack(tdb, vbuf.dptr, vbuf.dsize - len, "d", &pass.uni_name_len);
188         
189         for (idx = 0; idx < 32; idx++)
190                 len +=  tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "w", &pass.uni_name[idx]);
191
192         len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "d", &pass_len);
193         pass.pass = talloc_strdup(ctx, vbuf.dptr+len);
194         len += strlen(vbuf.dptr)+1;
195         len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "d", &pass.mod_time);
196         
197         pass.domain_sid.sub_auths = talloc_array(ctx, uint32_t, 15);
198         /* unpack domain sid */
199         len += tdb_sid_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, &pass.domain_sid);
200
201         /* FIXME: Add to list */
202
203         return NT_STATUS_OK;
204 }
205
206 static const struct {
207         const char *prefix;
208         NTSTATUS (*handler) (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db);
209 } secrets_handlers[] = {
210         { "SECRETS/AUTH_PASSWORD", ipc_password },
211         { "SECRETS/AUTH_DOMAIN", ipc_domain },
212         { "SECRETS/AUTH_USER", ipc_username },
213         { "SECRETS/SID/", domain_sid },
214         { "SECRETS/DOMGUID/", domain_guid },
215         { "SECRETS/LDAP_BIND_PW/", ldap_bind_pw },
216         { "SECRETS/AFS_KEYFILE/", afs_keyfile },
217         { "SECRETS/MACHINE_SEC_CHANNEL_TYPE/", machine_sec_channel_type },
218         { "SECRETS/MACHINE_LAST_CHANGE_TIME/", machine_last_change_time },
219         { "SECRETS/MACHINE_PASSWORD/", machine_password },
220         { "SECRETS/$MACHINE.ACC/", machine_acc },
221         { "SECRETS/$DOMTRUST.ACC/", domtrust_acc },
222         { "INFO/random_seed", random_seed },
223 };
224
225
226 NTSTATUS samba3_read_secrets(const char *fname, TALLOC_CTX *ctx, struct samba3_secrets *db)
227 {
228         TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600);
229         TDB_DATA kbuf, vbuf;
230
231         if (!tdb) {
232                 DEBUG(0,("Failed to open %s\n", fname));
233                 return NT_STATUS_UNSUCCESSFUL;
234         }
235
236         ZERO_STRUCTP(db);
237         
238         db->ipc_cred = cli_credentials_init(ctx);
239         
240         for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf))
241         {
242                 int i;
243                 char *key;
244                 vbuf = tdb_fetch(tdb, kbuf);
245
246                 for (i = 0; secrets_handlers[i].prefix; i++) {
247                         if (!strncmp(kbuf.dptr, secrets_handlers[i].prefix, strlen(secrets_handlers[i].prefix))) {
248                                 key = talloc_strndup(ctx, kbuf.dptr+strlen(secrets_handlers[i].prefix), kbuf.dsize-strlen(secrets_handlers[i].prefix));
249                                 secrets_handlers[i].handler(tdb, key, vbuf, ctx, db);
250                                 talloc_free(key);
251                                 break;
252                         }
253                 }
254
255                 if (!secrets_handlers[i].prefix) {
256                         DEBUG(0, ("Unable to find handler for string %s", kbuf.dptr));
257                 }
258         }
259         
260         tdb_close(tdb);
261
262         return NT_STATUS_OK;
263 }