lib: Pass mem_ctx to state_path()
[samba.git] / source3 / printing / nt_printing_migrate_internal.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *
5  *  Copyright (c) Andreas Schneider            2010.
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 3 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, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "printing/nt_printing_migrate.h"
24 #include "printing/nt_printing_migrate_internal.h"
25
26 #include "rpc_client/rpc_client.h"
27 #include "librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "librpc/gen_ndr/ndr_winreg.h"
29 #include "rpc_server/rpc_ncacn_np.h"
30 #include "auth.h"
31 #include "util_tdb.h"
32
33 #define FORMS_PREFIX "FORMS/"
34 #define DRIVERS_PREFIX "DRIVERS/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
37
38 static int rename_file_with_suffix(TALLOC_CTX *mem_ctx,
39                                    const char *path,
40                                    const char *suffix)
41 {
42         int rc = -1;
43         char *dst_path;
44
45         dst_path = talloc_asprintf(mem_ctx, "%s%s", path, suffix);
46         if (dst_path == NULL) {
47                 DEBUG(3, ("error out of memory\n"));
48                 return rc;
49         }
50
51         rc = (rename(path, dst_path) != 0);
52
53         if (rc == 0) {
54                 DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path));
55         } else if (errno == ENOENT) {
56                 DEBUG(3, ("file '%s' does not exist - so not moved\n", path));
57                 rc = 0;
58         } else {
59                 DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path,
60                           strerror(errno)));
61         }
62
63         TALLOC_FREE(dst_path);
64         return rc;
65 }
66
67 static NTSTATUS migrate_internal(TALLOC_CTX *mem_ctx,
68                                  const char *tdb_path,
69                                  struct rpc_pipe_client *winreg_pipe)
70 {
71         const char *backup_suffix = ".bak";
72         TDB_DATA kbuf, newkey, dbuf;
73         TDB_CONTEXT *tdb;
74         NTSTATUS status;
75         int rc;
76
77         tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
78         if (tdb == NULL && errno == ENOENT) {
79                 /* if we have no printers database then migration is
80                    considered successful */
81                 DEBUG(4, ("No printers database to migrate in %s\n", tdb_path));
82                 return NT_STATUS_OK;
83         }
84         if (tdb == NULL) {
85                 DEBUG(2, ("Failed to open tdb file: %s\n", tdb_path));
86                 return NT_STATUS_NO_SUCH_FILE;
87         }
88
89         for (kbuf = tdb_firstkey(tdb);
90              kbuf.dptr;
91              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
92         {
93                 dbuf = tdb_fetch(tdb, kbuf);
94                 if (!dbuf.dptr) {
95                         continue;
96                 }
97
98                 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
99                         status = printing_tdb_migrate_form(mem_ctx,
100                                               winreg_pipe,
101                                               (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
102                                               dbuf.dptr,
103                                               dbuf.dsize);
104                         SAFE_FREE(dbuf.dptr);
105                         if (!NT_STATUS_IS_OK(status)) {
106                                 tdb_close(tdb);
107                                 return status;
108                         }
109                         continue;
110                 }
111
112                 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
113                         status = printing_tdb_migrate_driver(mem_ctx,
114                                                 winreg_pipe,
115                                                 (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
116                                                 dbuf.dptr,
117                                                 dbuf.dsize,
118                                                 false);
119                         SAFE_FREE(dbuf.dptr);
120                         if (!NT_STATUS_IS_OK(status)) {
121                                 tdb_close(tdb);
122                                 return status;
123                         }
124                         continue;
125                 }
126
127                 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
128                         const char *printer_name = (const char *)(kbuf.dptr
129                                                     + strlen(PRINTERS_PREFIX));
130                         status = printing_tdb_migrate_printer(mem_ctx,
131                                                  winreg_pipe,
132                                                  printer_name,
133                                                  dbuf.dptr,
134                                                  dbuf.dsize,
135                                                  false);
136                         SAFE_FREE(dbuf.dptr);
137                         if (!NT_STATUS_IS_OK(status)) {
138                                 tdb_close(tdb);
139                                 return status;
140                         }
141                         continue;
142                 }
143                 SAFE_FREE(dbuf.dptr);
144         }
145
146         for (kbuf = tdb_firstkey(tdb);
147              kbuf.dptr;
148              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
149         {
150                 dbuf = tdb_fetch(tdb, kbuf);
151                 if (!dbuf.dptr) {
152                         continue;
153                 }
154
155                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
156                         const char *secdesc_name = (const char *)(kbuf.dptr
157                                                     + strlen(SECDESC_PREFIX));
158                         status = printing_tdb_migrate_secdesc(mem_ctx,
159                                                  winreg_pipe,
160                                                  secdesc_name,
161                                                  dbuf.dptr,
162                                                  dbuf.dsize);
163                         SAFE_FREE(dbuf.dptr);
164                         if (NT_STATUS_EQUAL(status, werror_to_ntstatus(WERR_FILE_NOT_FOUND))) {
165                                 DEBUG(2, ("Skipping secdesc migration for non-existent "
166                                                 "printer: %s\n", secdesc_name));
167                         } else if (!NT_STATUS_IS_OK(status)) {
168                                 tdb_close(tdb);
169                                 return status;
170                         }
171                         continue;
172                 }
173                 SAFE_FREE(dbuf.dptr);
174         }
175
176         tdb_close(tdb);
177
178         rc = rename_file_with_suffix(mem_ctx, tdb_path, backup_suffix);
179         if (rc != 0) {
180                 DEBUG(0, ("Error moving tdb to '%s%s'\n",
181                           tdb_path, backup_suffix));
182         }
183
184         return NT_STATUS_OK;
185 }
186
187 bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx)
188 {
189         const char *drivers_path;
190         const char *printers_path;
191         const char *forms_path;
192         bool drivers_exists;
193         bool printers_exists;
194         bool forms_exists;
195         struct auth_session_info *session_info;
196         struct rpc_pipe_client *winreg_pipe = NULL;
197         TALLOC_CTX *tmp_ctx = talloc_stackframe();
198         NTSTATUS status;
199
200         /* paths talloced on new stackframe */
201         drivers_path = state_path(talloc_tos(), "ntdrivers.tdb");
202         printers_path = state_path(talloc_tos(), "ntprinters.tdb");
203         forms_path = state_path(talloc_tos(), "ntforms.tdb");
204         if ((drivers_path == NULL) || (printers_path == NULL)
205                                                 || (forms_path == NULL)) {
206                 talloc_free(tmp_ctx);
207                 return false;
208         }
209         drivers_exists = file_exist(drivers_path);
210         printers_exists = file_exist(printers_path);
211         forms_exists = file_exist(forms_path);
212
213         if (!drivers_exists && !printers_exists && !forms_exists) {
214                 talloc_free(tmp_ctx);
215                 return true;
216         }
217
218         status = make_session_info_system(tmp_ctx, &session_info);
219         if (!NT_STATUS_IS_OK(status)) {
220                 DEBUG(0, ("Couldn't create session_info: %s\n",
221                           nt_errstr(status)));
222                 talloc_free(tmp_ctx);
223                 return false;
224         }
225
226         status = rpc_pipe_open_interface(tmp_ctx,
227                                         &ndr_table_winreg,
228                                         session_info,
229                                         NULL,
230                                         NULL,
231                                         msg_ctx,
232                                         &winreg_pipe);
233         if (!NT_STATUS_IS_OK(status)) {
234                 DEBUG(0, ("Couldn't open internal winreg pipe: %s\n",
235                           nt_errstr(status)));
236                 talloc_free(tmp_ctx);
237                 return false;
238         }
239
240         if (drivers_exists) {
241                 status = migrate_internal(tmp_ctx, drivers_path, winreg_pipe);
242                 if (!NT_STATUS_IS_OK(status)) {
243                         DEBUG(0, ("Couldn't migrate drivers tdb file: %s\n",
244                           nt_errstr(status)));
245                         talloc_free(tmp_ctx);
246                         return false;
247                 }
248         }
249
250         if (printers_exists) {
251                 status = migrate_internal(tmp_ctx, printers_path, winreg_pipe);
252                 if (!NT_STATUS_IS_OK(status)) {
253                         DEBUG(0, ("Couldn't migrate printers tdb file: %s\n",
254                                   nt_errstr(status)));
255                         talloc_free(tmp_ctx);
256                         return false;
257                 }
258         }
259
260         if (forms_exists) {
261                 status = migrate_internal(tmp_ctx, forms_path, winreg_pipe);
262                 if (!NT_STATUS_IS_OK(status)) {
263                         DEBUG(0, ("Couldn't migrate forms tdb file: %s\n",
264                                   nt_errstr(status)));
265                         talloc_free(tmp_ctx);
266                         return false;
267                 }
268         }
269
270         talloc_free(tmp_ctx);
271         return true;
272 }