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