1 #include "burp.h"
2 #include "alloc.h"
3 #include "cmd.h"
4 #include "iobuf.h"
5 #include "log.h"
6 #include "msg.h"
7 #include "pathcmp.h"
8 
iobuf_alloc(void)9 struct iobuf *iobuf_alloc(void)
10 {
11 	struct iobuf *iobuf;
12 	if(!(iobuf=(struct iobuf *)calloc_w(1, sizeof(struct iobuf), __func__)))
13 		return NULL;
14 	iobuf_init(iobuf);
15 	return iobuf;
16 }
17 
iobuf_set(struct iobuf * iobuf,enum cmd cmd,char * buf,size_t len)18 void iobuf_set(struct iobuf *iobuf, enum cmd cmd, char *buf, size_t len)
19 {
20 	iobuf->cmd=cmd;
21 	iobuf->buf=buf;
22 	iobuf->len=len;
23 }
24 
iobuf_init(struct iobuf * iobuf)25 void iobuf_init(struct iobuf *iobuf)
26 {
27 	iobuf_set(iobuf, CMD_ERROR, NULL, 0);
28 }
29 
iobuf_free_content(struct iobuf * iobuf)30 void iobuf_free_content(struct iobuf *iobuf)
31 {
32 	if(!iobuf) return;
33 	free_w(&iobuf->buf);
34 	iobuf_init(iobuf);
35 }
36 
iobuf_free(struct iobuf ** iobuf)37 void iobuf_free(struct iobuf **iobuf)
38 {
39 	if(!iobuf || !*iobuf) return;
40 	iobuf_free_content(*iobuf);
41 	free_v((void **)iobuf);
42 }
43 
iobuf_log_unexpected(struct iobuf * iobuf,const char * func)44 void iobuf_log_unexpected(struct iobuf *iobuf, const char *func)
45 {
46 	logp("unexpected command in %s(): %s\n",
47 		func, iobuf_to_printable(iobuf));
48 }
49 
iobuf_copy(struct iobuf * dst,struct iobuf * src)50 void iobuf_copy(struct iobuf *dst, struct iobuf *src)
51 {
52 	iobuf_set(dst, src->cmd, src->buf, src->len);
53 }
54 
iobuf_move(struct iobuf * dst,struct iobuf * src)55 void iobuf_move(struct iobuf *dst, struct iobuf *src)
56 {
57 	iobuf_copy(dst, src);
58 	src->buf=NULL;
59 }
60 
iobuf_from_str(struct iobuf * iobuf,enum cmd cmd,char * str)61 void iobuf_from_str(struct iobuf *iobuf, enum cmd cmd, char *str)
62 {
63 	iobuf_set(iobuf, cmd, str, strlen(str));
64 }
65 
iobuf_send_msg_fzp(struct iobuf * iobuf,struct fzp * fzp)66 int iobuf_send_msg_fzp(struct iobuf *iobuf, struct fzp *fzp)
67 {
68 	return send_msg_fzp(fzp, iobuf->cmd, iobuf->buf, iobuf->len);
69 }
70 
iobuf_pathcmp(struct iobuf * a,struct iobuf * b)71 int iobuf_pathcmp(struct iobuf *a, struct iobuf *b)
72 {
73 	int r;
74 	if((r=pathcmp(a->buf, b->buf))) return r;
75 	if(a->cmd==CMD_METADATA || a->cmd==CMD_ENC_METADATA)
76 	{
77 		if(b->cmd==CMD_METADATA || b->cmd==CMD_ENC_METADATA) return 0;
78 		else return 1;
79 	}
80 	else if(a->cmd==CMD_VSS || a->cmd==CMD_ENC_VSS)
81 	{
82 		if(b->cmd==CMD_VSS || b->cmd==CMD_ENC_VSS) return 0;
83 		else return -1;
84 	}
85 	else if(a->cmd==CMD_VSS_T || a->cmd==CMD_ENC_VSS_T)
86 	{
87 		if(b->cmd==CMD_VSS_T || b->cmd==CMD_ENC_VSS_T) return 0;
88 		else return 1;
89 	}
90 	else
91 	{
92 		if(b->cmd==CMD_METADATA || b->cmd==CMD_ENC_METADATA) return -1;
93 		else if(b->cmd==CMD_VSS || b->cmd==CMD_ENC_VSS) return 1;
94 		else if(b->cmd==CMD_VSS_T || b->cmd==CMD_ENC_VSS_T) return -1;
95 		else return 0;
96 	}
97 }
98 
iobuf_is_filedata(struct iobuf * iobuf)99 int iobuf_is_filedata(struct iobuf *iobuf)
100 {
101 	return cmd_is_filedata(iobuf->cmd);
102 }
103 
iobuf_is_vssdata(struct iobuf * iobuf)104 int iobuf_is_vssdata(struct iobuf *iobuf)
105 {
106 	return cmd_is_vssdata(iobuf->cmd);
107 }
108 
iobuf_is_link(struct iobuf * iobuf)109 int iobuf_is_link(struct iobuf *iobuf)
110 {
111 	return cmd_is_link(iobuf->cmd);
112 }
113 
iobuf_is_encrypted(struct iobuf * iobuf)114 int iobuf_is_encrypted(struct iobuf *iobuf)
115 {
116 	return cmd_is_encrypted(iobuf->cmd);
117 }
118 
iobuf_is_metadata(struct iobuf * iobuf)119 int iobuf_is_metadata(struct iobuf *iobuf)
120 {
121 	return cmd_is_metadata(iobuf->cmd);
122 }
123 
iobuf_is_estimatable(struct iobuf * iobuf)124 int iobuf_is_estimatable(struct iobuf *iobuf)
125 {
126 	return cmd_is_estimatable(iobuf->cmd);
127 }
128 
do_iobuf_fill_from_fzp(struct iobuf * iobuf,struct fzp * fzp,int extra_bytes)129 static int do_iobuf_fill_from_fzp(struct iobuf *iobuf, struct fzp *fzp,
130 	int extra_bytes)
131 {
132 	unsigned int s;
133 	char lead[6]="";
134 	char command;
135 	int r;
136 
137 	r=fzp_read_ensure(fzp, lead, sizeof(lead)-1, __func__);
138 	lead[5]='\0';
139 	switch(r)
140 	{
141 		case 0: break; // OK.
142 		case 1: return 1; // Finished OK.
143 		default:
144 		{
145 			logp("Error reading lead in %s\n", __func__);
146 			return -1; // Error.
147 		}
148 	}
149 	if((sscanf(lead, "%c%04X", &command, &s))!=2)
150 	{
151 		logp("sscanf failed reading manifest: %s\n", lead);
152 		return -1;
153 	}
154 	iobuf->cmd=(enum cmd)command;
155 	iobuf->len=(size_t)s;
156 	if(!(iobuf->buf=(char *)malloc_w(
157 		iobuf->len+extra_bytes+1, __func__)))
158 			return -1;
159 	switch(fzp_read_ensure(fzp,
160 		iobuf->buf, iobuf->len+extra_bytes, __func__))
161 	{
162 		case 0: break; // OK.
163 		case 1: return 1; // Finished OK.
164 		default:
165 			logp("Error attempting to read after %s in %s (%c:%u)\n", lead, __func__, iobuf->cmd, s);
166 			return -1;
167 	}
168 	iobuf->buf[iobuf->len]='\0';
169 	return 0;
170 }
171 
iobuf_fill_from_fzp(struct iobuf * iobuf,struct fzp * fzp)172 int iobuf_fill_from_fzp(struct iobuf *iobuf, struct fzp *fzp)
173 {
174 	return do_iobuf_fill_from_fzp(iobuf, fzp, 1 /*newline*/);
175 }
176 
iobuf_fill_from_fzp_data(struct iobuf * iobuf,struct fzp * fzp)177 int iobuf_fill_from_fzp_data(struct iobuf *iobuf, struct fzp *fzp)
178 {
179 	return do_iobuf_fill_from_fzp(iobuf, fzp, 0 /*no newline*/);
180 }
181 
is_printable(struct iobuf * iobuf)182 static int is_printable(struct iobuf *iobuf)
183 {
184 	size_t l;
185 	for(l=0; l<iobuf->len; l++)
186 		if(!isprint(iobuf->buf[l]) && iobuf->buf[l]!='\n')
187 			return 0;
188 	return 1;
189 }
190 
iobuf_to_printable(struct iobuf * iobuf)191 const char *iobuf_to_printable(struct iobuf *iobuf)
192 {
193 	static char str[256]="";
194 	if(is_printable(iobuf))
195 		snprintf(str, sizeof(str),
196 			"%c:%04X:%s", iobuf->cmd, (int)iobuf->len, iobuf->buf);
197 	else
198 		snprintf(str, sizeof(str),
199 			"%c:%04X:(binary data)", iobuf->cmd, (int)iobuf->len);
200 	return str;
201 }
202 
iobuf_relative_path_attack(struct iobuf * iobuf)203 int iobuf_relative_path_attack(struct iobuf *iobuf)
204 {
205 	if(!has_dot_component(iobuf->buf))
206 		return 0;
207 	iobuf_log_unexpected(iobuf, __func__);
208 	return 1;
209 }
210 
211