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