s3-param: Rename loadparm_s3_context -> loadparm_s3_helpers
[kai/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, 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_compat(tdb);
90              kbuf.dptr;
91              kbuf = tdb_nextkey_compat(tdb, kbuf))
92         {
93                 dbuf = tdb_fetch_compat(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                         SAFE_FREE(dbuf.dptr);
119                         if (!NT_STATUS_IS_OK(status)) {
120                                 tdb_close(tdb);
121                                 return status;
122                         }
123                         continue;
124                 }
125
126                 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
127                         const char *printer_name = (const char *)(kbuf.dptr
128                                                     + strlen(PRINTERS_PREFIX));
129                         status = printing_tdb_migrate_printer(mem_ctx,
130                                                  winreg_pipe,
131                                                  printer_name,
132                                                  dbuf.dptr,
133                                                  dbuf.dsize);
134                         SAFE_FREE(dbuf.dptr);
135                         if (!NT_STATUS_IS_OK(status)) {
136                                 tdb_close(tdb);
137                                 return status;
138                         }
139                         continue;
140                 }
141                 SAFE_FREE(dbuf.dptr);
142         }
143
144         for (kbuf = tdb_firstkey_compat(tdb);
145              kbuf.dptr;
146              kbuf = tdb_nextkey_compat(tdb, kbuf))
147         {
148                 dbuf = tdb_fetch_compat(tdb, kbuf);
149                 if (!dbuf.dptr) {
150                         continue;
151                 }
152
153                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
154                         const char *secdesc_name = (const char *)(kbuf.dptr
155                                                     + strlen(SECDESC_PREFIX));
156                         status = printing_tdb_migrate_secdesc(mem_ctx,
157                                                  winreg_pipe,
158                                                  secdesc_name,
159                                                  dbuf.dptr,
160                                                  dbuf.dsize);
161                         SAFE_FREE(dbuf.dptr);
162                         if (NT_STATUS_EQUAL(status, werror_to_ntstatus(WERR_BADFILE))) {
163                                 DEBUG(2, ("Skipping secdesc migration for non-existent "
164                                                 "printer: %s\n", secdesc_name));
165                         } else if (!NT_STATUS_IS_OK(status)) {
166                                 tdb_close(tdb);
167                                 return status;
168                         }
169                         continue;
170                 }
171                 SAFE_FREE(dbuf.dptr);
172         }
173
174         tdb_close(tdb);
175
176         rc = rename_file_with_suffix(mem_ctx, tdb_path, backup_suffix);
177         if (rc != 0) {
178                 DEBUG(0, ("Error moving tdb to '%s%s'\n",
179                           tdb_path, backup_suffix));
180         }
181
182         return NT_STATUS_OK;
183 }
184
185 bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx)
186 {
187         const char *drivers_path = state_path("ntdrivers.tdb");
188         const char *printers_path = state_path("ntprinters.tdb");
189         const char *forms_path = state_path("ntforms.tdb");
190         bool drivers_exists = file_exist(drivers_path);
191         bool printers_exists = file_exist(printers_path);
192         bool forms_exists = file_exist(forms_path);
193         struct auth_session_info *session_info;
194         struct rpc_pipe_client *winreg_pipe = NULL;
195         TALLOC_CTX *tmp_ctx = talloc_stackframe();
196         NTSTATUS status;
197
198         if (!drivers_exists && !printers_exists && !forms_exists) {
199                 return true;
200         }
201
202         status = make_session_info_system(tmp_ctx, &session_info);
203         if (!NT_STATUS_IS_OK(status)) {
204                 DEBUG(0, ("Couldn't create session_info: %s\n",
205                           nt_errstr(status)));
206                 talloc_free(tmp_ctx);
207                 return false;
208         }
209
210         status = rpc_pipe_open_interface(tmp_ctx,
211                                         &ndr_table_winreg.syntax_id,
212                                         session_info,
213                                         NULL,
214                                         msg_ctx,
215                                         &winreg_pipe);
216         if (!NT_STATUS_IS_OK(status)) {
217                 DEBUG(0, ("Couldn't open internal winreg pipe: %s\n",
218                           nt_errstr(status)));
219                 talloc_free(tmp_ctx);
220                 return false;
221         }
222
223         if (drivers_exists) {
224                 status = migrate_internal(tmp_ctx, drivers_path, winreg_pipe);
225                 if (!NT_STATUS_IS_OK(status)) {
226                         DEBUG(0, ("Couldn't migrate drivers tdb file: %s\n",
227                           nt_errstr(status)));
228                         talloc_free(tmp_ctx);
229                         return false;
230                 }
231         }
232
233         if (printers_exists) {
234                 status = migrate_internal(tmp_ctx, printers_path, winreg_pipe);
235                 if (!NT_STATUS_IS_OK(status)) {
236                         DEBUG(0, ("Couldn't migrate printers tdb file: %s\n",
237                                   nt_errstr(status)));
238                         talloc_free(tmp_ctx);
239                         return false;
240                 }
241         }
242
243         if (forms_exists) {
244                 status = migrate_internal(tmp_ctx, forms_path, winreg_pipe);
245                 if (!NT_STATUS_IS_OK(status)) {
246                         DEBUG(0, ("Couldn't migrate forms tdb file: %s\n",
247                                   nt_errstr(status)));
248                         talloc_free(tmp_ctx);
249                         return false;
250                 }
251         }
252
253         talloc_free(tmp_ctx);
254         return true;
255 }