1 #include "../burp.h"
2 #include "../alloc.h"
3 #include "../berrno.h"
4 #include "../bfile.h"
5 #include "../cmd.h"
6 #include "../cntr.h"
7 #include "../log.h"
8 #include "../strlist.h"
9 #include "cvss.h"
10 #include "extrameta.h"
11
12 #if defined(WIN32_VSS)
13 #include "vss.h"
14
15 // Attempt to stop VSS nicely if the client is interrupted by the user.
CtrlHandler(DWORD fdwCtrlType)16 BOOL CtrlHandler(DWORD fdwCtrlType)
17 {
18 switch(fdwCtrlType)
19 {
20 // Handle the CTRL-C signal.
21 case CTRL_C_EVENT:
22 case CTRL_CLOSE_EVENT:
23 case CTRL_BREAK_EVENT:
24 win32_stop_vss();
25 return FALSE;
26 default:
27 return FALSE;
28 }
29 }
30
win32_start_vss(struct asfd * asfd,struct conf ** confs)31 int win32_start_vss(struct asfd *asfd, struct conf **confs)
32 {
33 int errors=0;
34 struct cntr *cntr=get_cntr(confs);
35 const char *drives_vss=get_string(confs[OPT_VSS_DRIVES]);
36
37 if(SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE))
38 logp("Control handler registered.\n");
39 else
40 {
41 logw(asfd, cntr, "Could not register control handler.\n");
42 errors++;
43 return errors;
44 }
45
46 if(g_pVSSClient->InitializeForBackup(asfd, cntr))
47 {
48 char szWinDriveLetters[27];
49 // Tell vss which drives to snapshot.
50 if(drives_vss)
51 {
52 unsigned int i=0;
53 for(i=0; i<strlen(drives_vss) && i<26; i++)
54 szWinDriveLetters[i]=toupper(drives_vss[i]);
55 szWinDriveLetters[i]='\0';
56 }
57 else
58 {
59 // Not given anything specific. Figure out what to do
60 // from the given starting directories.
61 int j=0;
62 struct strlist *s;
63 for(s=get_strlist(confs[OPT_STARTDIR]), j=0;
64 s && j<26; s=s->next)
65 {
66 const char *path=NULL;
67 if(!s->flag) continue;
68 path=s->path;
69 if(strlen(path)>2
70 && isalpha(path[0]) && path[1]==':')
71 {
72 int x=0;
73 // Try not to add the same letter twice.
74 for(x=0; x<j; x++)
75 if(toupper(path[0])==szWinDriveLetters[x])
76 break;
77 if(x<j) continue;
78 szWinDriveLetters[j++]=toupper(path[0]);
79 }
80 }
81 szWinDriveLetters[j]='\0';
82 }
83 logp("Generate VSS snapshots.\n");
84 logp("Driver=\"%s\", Drive(s)=\"%s\"\n",
85 g_pVSSClient->GetDriverName(),
86 szWinDriveLetters);
87 if(!g_pVSSClient->CreateSnapshots(szWinDriveLetters))
88 {
89 berrno be;
90 berrno_init(&be);
91 logw(asfd, cntr,
92 "Generate VSS snapshots failed.ERR=%s\n",
93 berrno_bstrerror(&be, b_errno_win32));
94 errors++;
95 }
96 else
97 {
98 int i;
99 for(i=0; i<(int)strlen(szWinDriveLetters); i++)
100 {
101 logp("VSS drive letters: %d\n", i);
102 if(islower(szWinDriveLetters[i]))
103 {
104 logw(asfd, cntr, "Generate VSS snapshot of drive \"%c:\\\" failed.\n", szWinDriveLetters[i]);
105 errors++;
106 }
107 }
108
109 for(i=0; i<(int)g_pVSSClient->GetWriterCount(); i++)
110 {
111 if(g_pVSSClient->GetWriterState(i)<1)
112 {
113 logw(asfd, cntr,
114 "Start GetWriterState(%d)<1\n", i);
115 errors++;
116 }
117 logp("VSS Writer (PrepareForBackup): %s\n",
118 g_pVSSClient->GetWriterInfo(i));
119 }
120 }
121 }
122 else
123 {
124 berrno be;
125 berrno_init(&be);
126 logw(asfd, cntr, "VSS was not initialized properly. ERR=%s",
127 berrno_bstrerror(&be, b_errno_win32));
128 errors++;
129 }
130
131 return errors;
132 }
133
win32_stop_vss(void)134 int win32_stop_vss(void)
135 {
136 int errors=0;
137
138 if(g_pVSSClient->CloseBackup())
139 {
140 int i=0;
141 for(i=0; i<(int)g_pVSSClient->GetWriterCount(); i++)
142 {
143 if(g_pVSSClient->GetWriterState(i)<1)
144 {
145 // Would be better to be a logw, but this gets
146 // called by some weird handler thing above, so
147 // it is hard to pass in asfd and cntr.
148 logp("Stop GetWriterState(%d)<1\n", i);
149 errors++;
150 }
151 logp("VSS Writer (BackupComplete): %s\n",
152 g_pVSSClient->GetWriterInfo(i));
153 }
154 }
155 Win32ConvCleanupCache();
156 return errors;
157 }
158
159 #endif // WIN32_VSS
160
161 #if defined(HAVE_WIN32)
162
enable_priv(HANDLE hToken,const char * name)163 static int enable_priv(HANDLE hToken, const char *name)
164 {
165 TOKEN_PRIVILEGES tkp;
166 DWORD lerror;
167
168 if(!(p_LookupPrivilegeValue && p_AdjustTokenPrivileges))
169 return 0; /* not avail on this OS */
170
171 // Get the LUID for the security privilege.
172 if(!p_LookupPrivilegeValue(NULL, name, &tkp.Privileges[0].Luid))
173 {
174 logp("LookupPrivilegeValue: %lu\n",
175 (unsigned long)GetLastError());
176 return 0;
177 }
178
179 /* Set the security privilege for this process. */
180 tkp.PrivilegeCount=1;
181 tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
182 p_AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL);
183 lerror=GetLastError();
184 if(lerror==ERROR_SUCCESS) return 0;
185 logp("Could not set privilege %s\n", name);
186 return 1;
187 }
188
189 /*
190 * Setup privileges we think we will need. We probably do not need
191 * the SE_SECURITY_NAME, but since nothing seems to be working,
192 * we get it hoping to fix the problems.
193 */
win32_enable_backup_privileges()194 int win32_enable_backup_privileges()
195 {
196 int ret=0;
197 HANDLE hToken;
198 HANDLE hProcess;
199
200 if(!p_OpenProcessToken) return 0; /* No avail on this OS */
201
202 hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
203
204 // Get a token for this process.
205 if(!p_OpenProcessToken(hProcess,
206 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
207 {
208 logp("Could not OpenProcessToken\n");
209 /* Forge on anyway */
210 }
211
212 if(enable_priv(hToken, SE_BACKUP_NAME)) ret=-1;
213 if(enable_priv(hToken, SE_RESTORE_NAME)) ret=-1;
214 if(enable_priv(hToken, SE_SECURITY_NAME)) ret=-1;
215 /*
216 enable_priv(hToken, SE_TAKE_OWNERSHIP_NAME);
217 enable_priv(hToken, SE_ASSIGNPRIMARYTOKEN_NAME);
218 enable_priv(hToken, SE_SYSTEM_ENVIRONMENT_NAME);
219 enable_priv(hToken, SE_CREATE_TOKEN_NAME);
220 enable_priv(hToken, SE_MACHINE_ACCOUNT_NAME);
221 enable_priv(hToken, SE_TCB_NAME);
222 enable_priv(hToken, SE_CREATE_PERMANENT_NAME);
223 */
224
225 CloseHandle(hToken);
226 CloseHandle(hProcess);
227
228 if(ret)
229 {
230 logp("Some privileges were not enabled.\n\n");
231 logp("Are you running as Administrator?\n\n");
232 }
233 return ret;
234 }
235
ensure_read(BFILE * bfd,char * buf,size_t s,int print_err)236 static int ensure_read(BFILE *bfd, char *buf, size_t s, int print_err)
237 {
238 ssize_t got=0;
239 size_t offset=0;
240 while((got=bfd->read(bfd, buf+offset, s-offset))>0)
241 {
242 offset+=got;
243 if(offset>=s) break;
244 }
245 if(offset!=s)
246 {
247 if(print_err)
248 logp("Error in read - got %lu, wanted %lu\n",
249 (unsigned long)offset,
250 (unsigned long)s);
251 return -1;
252 }
253 return 0;
254 }
255
get_vss(BFILE * bfd,char ** vssdata,size_t * vlen)256 int get_vss(BFILE *bfd, char **vssdata, size_t *vlen)
257 {
258 bsid sid;
259 char *tmp=NULL;
260 *vlen=0;
261 while(!ensure_read(bfd, (char *)&sid, bsidsize, 0))
262 {
263 int64_t s=0;
264
265 if(!(tmp=(char *)realloc_w(tmp, (*vlen)+bsidsize, __func__)))
266 goto error;
267 memcpy(tmp+(*vlen), &sid, bsidsize);
268 (*vlen)+=bsidsize;
269
270 // dwStreamId==1 means start of backup data, so finish.
271 if(sid.dwStreamId==1)
272 {
273 // logp("\n%s: %d + %d\n",
274 // path, (int)sid.Size, (int)sid.dwStreamNameSize);
275 bfd->datalen=sid.Size;
276 break;
277 }
278
279 // Otherwise, need to read in the rest of the VSS header.
280 s=(sid.Size)+(sid.dwStreamNameSize);
281 if(!(tmp=(char *)realloc_w(tmp, (*vlen)+s, __func__))
282 || ensure_read(bfd, tmp+(*vlen), s, 1))
283 {
284 goto error;
285 return -1;
286 }
287 (*vlen)+=s;
288 }
289 if(!(*vssdata=(char *)realloc_w(*vssdata, (*vlen)+9, __func__)))
290 goto error;
291 snprintf(*vssdata, 9, "%c%08X", META_VSS, (unsigned int)*vlen);
292 memcpy((*vssdata)+9, tmp, *vlen);
293 (*vlen)+=9;
294 free_w(&tmp);
295 return 0;
296 error:
297 free_w(&tmp);
298 free_w(vssdata);
299 *vlen=0;
300 return -1;
301 }
302
ensure_write(BFILE * bfd,const char * buf,size_t got)303 static int ensure_write(BFILE *bfd, const char *buf, size_t got)
304 {
305 size_t wrote=0;
306 while((wrote=bfd->write(bfd, (void *)buf, got))>0)
307 {
308 got-=wrote;
309 if(got<=0) return 0;
310 }
311 logp("error when writing VSS data\n");
312 return -1;
313 }
314
set_vss(BFILE * bfd,const char * vssdata,size_t vlen)315 int set_vss(BFILE *bfd, const char *vssdata, size_t vlen)
316 {
317 // Just need to write the VSS stuff to the file.
318 if(!vlen || !vssdata) return 0;
319 return ensure_write(bfd, vssdata, vlen);
320 }
321
322 #endif /* HAVE_WIN32 */
323