1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2018 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Written by James Harper, July 2010
21  *
22  *  Used only in "old Exchange plugin" now deprecated.
23  */
24 
25 #include "exchange-fd.h"
26 
dbi_node_t(char * name,node_t * parent_node)27 dbi_node_t::dbi_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_DATABASE_INFO, parent_node)
28 {
29    restore_display_name = NULL;
30    restore_input_streams = NULL;
31    buffer = NULL;
32 }
33 
~dbi_node_t()34 dbi_node_t::~dbi_node_t()
35 {
36    safe_delete(buffer);
37    safe_delete(restore_input_streams);
38    safe_delete(restore_display_name);
39 }
40 
41 bRC
startBackupFile(exchange_fd_context_t * context,struct save_pkt * sp)42 dbi_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
43 {
44    time_t now = time(NULL);
45 
46    _DebugMessage(100, "startBackupNode_DBI state = %d\n", state);
47 
48    if (context->job_level == 'F') {
49       sp->fname = full_path;
50       sp->link = full_path;
51       sp->statp.st_mode = 0700 | S_IFREG;
52       sp->statp.st_ctime = now;
53       sp->statp.st_mtime = now;
54       sp->statp.st_atime = now;
55       sp->statp.st_size = (uint64_t)-1;
56       sp->type = FT_REG;
57       return bRC_OK;
58    }
59    else
60    {
61       bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)full_path);
62       return bRC_Seen;
63    }
64 }
65 
66 bRC
endBackupFile(exchange_fd_context_t * context)67 dbi_node_t::endBackupFile(exchange_fd_context_t *context)
68 {
69    _DebugMessage(100, "endBackupNode_DBI state = %d\n", state);
70 
71    context->current_node = parent;
72 
73    return bRC_OK;
74 }
75 
76 bRC
createFile(exchange_fd_context_t * context,struct restore_pkt * rp)77 dbi_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
78 {
79    _DebugMessage(0, "createFile_DBI state = %d\n", state);
80 
81    rp->create_status = CF_EXTRACT;
82 
83    return bRC_OK;
84 }
85 
86 bRC
endRestoreFile(exchange_fd_context_t * context)87 dbi_node_t::endRestoreFile(exchange_fd_context_t *context)
88 {
89    _DebugMessage(0, "endRestoreFile_DBI state = %d\n", state);
90 
91    context->current_node = parent;
92 
93    return bRC_OK;
94 }
95 
96 bRC
pluginIoOpen(exchange_fd_context_t * context,struct io_pkt * io)97 dbi_node_t::pluginIoOpen(exchange_fd_context_t *context, struct io_pkt *io)
98 {
99    uint32_t len;
100    WCHAR *ptr;
101    WCHAR *stream;
102    //char tmp[512];
103 
104    buffer_pos = 0;
105    buffer_size = 65536;
106    buffer = new char[buffer_size];
107 
108    if (context->job_type == JOB_TYPE_BACKUP)
109    {
110       ptr = (WCHAR *)buffer;
111       len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"DatabaseBackupInfo\n");
112       if (len < 0)
113          goto fail;
114       buffer_pos += len * 2;
115       ptr += len;
116 
117       len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%d\n", EXCHANGE_PLUGIN_VERSION);
118       if (len < 0)
119          goto fail;
120       buffer_pos += len * 2;
121       ptr += len;
122 
123       len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%s\n", dbi->wszDatabaseDisplayName);
124       if (len < 0)
125          goto fail;
126       buffer_pos += len * 2;
127       ptr += len;
128 
129       len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
130          dbi->rguidDatabase.Data1, dbi->rguidDatabase.Data2, dbi->rguidDatabase.Data3,
131          dbi->rguidDatabase.Data4[0], dbi->rguidDatabase.Data4[1],
132          dbi->rguidDatabase.Data4[2], dbi->rguidDatabase.Data4[3],
133          dbi->rguidDatabase.Data4[4], dbi->rguidDatabase.Data4[5],
134          dbi->rguidDatabase.Data4[6], dbi->rguidDatabase.Data4[7]);
135       if (len < 0)
136          goto fail;
137       buffer_pos += len * 2;
138       ptr += len;
139 
140       stream = dbi->wszDatabaseStreams;
141       while (*stream)
142       {
143          len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%s\n", stream);
144          if (len < 0)
145             goto fail;
146          buffer_pos += len * 2;
147          ptr += len;
148          stream += wcslen(stream) + 1;
149       }
150 
151       buffer_size = buffer_pos;
152       buffer_pos = 0;
153    }
154 
155    io->status = 0;
156    io->io_errno = 0;
157    return bRC_OK;
158 
159 fail:
160    io->status = 0;
161    io->io_errno = 1;
162    return bRC_Error;
163 }
164 
165 bRC
pluginIoRead(exchange_fd_context_t * context,struct io_pkt * io)166 dbi_node_t::pluginIoRead(exchange_fd_context_t *context, struct io_pkt *io)
167 {
168    io->status = 0;
169    io->io_errno = 0;
170 
171    io->status = MIN(io->count, (int)(buffer_size - buffer_pos));
172    if (io->status == 0)
173       return bRC_OK;
174    memcpy(io->buf, buffer + buffer_pos, io->status);
175    buffer_pos += io->status;
176 
177    return bRC_OK;
178 }
179 
180 bRC
pluginIoWrite(exchange_fd_context_t * context,struct io_pkt * io)181 dbi_node_t::pluginIoWrite(exchange_fd_context_t *context, struct io_pkt *io)
182 {
183    memcpy(&buffer[buffer_pos], io->buf, io->count);
184    buffer_pos += io->count;
185    io->status = io->count;
186    io->io_errno = 0;
187    return bRC_OK;
188 }
189 
190 bRC
pluginIoClose(exchange_fd_context_t * context,struct io_pkt * io)191 dbi_node_t::pluginIoClose(exchange_fd_context_t *context, struct io_pkt *io)
192 {
193    WCHAR tmp[128];
194    WCHAR *ptr;
195    WCHAR eol;
196    int wchars_read;
197    int version;
198    int stream_buf_count;
199    WCHAR *streams_start;
200 
201    if (context->job_type == JOB_TYPE_RESTORE)
202    {
203       // need to think about making this buffer overflow proof...
204       _DebugMessage(100, "analyzing DatabaseBackupInfo\n");
205       ptr = (WCHAR *)buffer;
206 
207       if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
208          goto restore_fail;
209       ptr += wchars_read;
210       _DebugMessage(150, "Header = %S\n", tmp);
211       // verify that header == "DatabaseBackupInfo"
212 
213       if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
214          goto restore_fail;
215       if (swscanf(tmp, L"%d%c", &version, &eol) != 1)
216       {
217          version = 0;
218          _DebugMessage(150, "Version = 0 (inferred)\n");
219       }
220       else
221       {
222          ptr += wchars_read;
223          _DebugMessage(150, "Version = %d\n", version);
224          if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
225             goto restore_fail;
226       }
227       restore_display_name = new WCHAR[wchars_read];
228       swscanf(ptr, L"%127[^\n]", restore_display_name);
229       _DebugMessage(150, "Database Display Name = %S\n", restore_display_name);
230       ptr += wchars_read;
231 
232       if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
233          goto restore_fail;
234 
235       if (swscanf(ptr, L"%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
236          &restore_guid.Data1, &restore_guid.Data2, &restore_guid.Data3,
237          &restore_guid.Data4[0], &restore_guid.Data4[1],
238          &restore_guid.Data4[2], &restore_guid.Data4[3],
239          &restore_guid.Data4[4], &restore_guid.Data4[5],
240          &restore_guid.Data4[6], &restore_guid.Data4[7]) != 11)
241       {
242          goto restore_fail;
243       }
244          _DebugMessage(150, "GUID = %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
245          restore_guid.Data1, restore_guid.Data2, restore_guid.Data3,
246          restore_guid.Data4[0], restore_guid.Data4[1],
247          restore_guid.Data4[2], restore_guid.Data4[3],
248          restore_guid.Data4[4], restore_guid.Data4[5],
249          restore_guid.Data4[6], restore_guid.Data4[7]);
250 
251       ptr += wchars_read;
252 
253       stream_buf_count = 1;
254       streams_start = ptr;
255       while (ptr < (WCHAR *)(buffer + buffer_pos) && swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) == 2)
256       {
257          _DebugMessage(150, "File = %S\n", tmp);
258          ptr += wchars_read;
259          stream_buf_count += wchars_read;
260       }
261       restore_input_streams = new WCHAR[stream_buf_count];
262       ptr = streams_start;
263       stream_buf_count = 0;
264       while (ptr < (WCHAR *)(buffer + buffer_pos) && swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) == 2)
265       {
266          snwprintf(&restore_input_streams[stream_buf_count], 65535, L"%s", tmp);
267          ptr += wchars_read;
268          stream_buf_count += wchars_read;
269       }
270       restore_input_streams[stream_buf_count] = 0;
271 
272       _DebugMessage(100, "done analyzing DatabasePluginInfo\n");
273    }
274    safe_delete(buffer);
275    return bRC_OK;
276 restore_fail:
277    _JobMessage(M_FATAL, "Format of %s is incorrect", full_path);
278    safe_delete(buffer);
279    return bRC_Error;
280 }
281