@@ -135,102 +135,65 @@ start_sending_dir(struct pss_deaddrop *pss)
135135static int
136136scan_upload_dir (struct vhd_deaddrop * vhd )
137137{
138- char filepath [256 ], subdir [ 3 ][ 128 ], * p ;
138+ char filepath [512 ], * p_owner_end ;
139139 struct lwsac * lwsac_head = NULL ;
140140 lws_list_ptr sorted_head = NULL ;
141141 struct dir_entry * dire ;
142142 struct dirent * de ;
143- size_t initial , m ;
144- int i , sp = 0 ;
143+ size_t m ;
145144 struct stat s ;
146- DIR * dir [ 3 ] ;
145+ DIR * dir ;
147146
148- initial = strlen (vhd -> upload_dir ) + 1 ;
149- lws_strncpy (subdir [sp ], vhd -> upload_dir , sizeof (subdir [sp ]));
150- dir [sp ] = opendir (vhd -> upload_dir );
151- if (!dir [sp ]) {
147+ dir = opendir (vhd -> upload_dir );
148+ if (!dir ) {
152149 lwsl_err ("%s: Unable to walk upload dir '%s'\n" , __func__ ,
153150 vhd -> upload_dir );
154151 return -1 ;
155152 }
156153
157- do {
158- de = readdir (dir [sp ]);
159- if (!de ) {
160- closedir (dir [sp ]);
161- #if !defined(__COVERITY__ )
162- if (!sp )
163- #endif
164- break ;
165- #if !defined(__COVERITY__ )
166- sp -- ;
154+ while ((de = readdir (dir ))) {
155+ /* ignore temp files */
156+ if (de -> d_name [strlen (de -> d_name ) - 1 ] == '~' ||
157+ !strcmp (de -> d_name , "." ) || !strcmp (de -> d_name , ".." ))
167158 continue ;
168- #endif
169- }
170159
171- p = filepath ;
160+ lws_snprintf (filepath , sizeof (filepath ), "%s/%s" ,
161+ vhd -> upload_dir , de -> d_name );
172162
173- for (i = 0 ; i <= sp ; i ++ )
174- p += lws_snprintf (p , lws_ptr_diff_size_t ((filepath + sizeof (filepath )), p ),
175- "%s/" , subdir [i ]);
176-
177- lws_snprintf (p , lws_ptr_diff_size_t ((filepath + sizeof (filepath )), p ), "%s" ,
178- de -> d_name );
179-
180- /* ignore temp files */
181- if (de -> d_name [strlen (de -> d_name ) - 1 ] == '~' )
182- continue ;
183- #if defined(__COVERITY__ )
184- s .st_size = 0 ;
185- s .st_mtime = 0 ;
186- #else
187- /* coverity[toctou] */
188163 if (stat (filepath , & s ))
189164 continue ;
190165
191- if (S_ISDIR (s .st_mode )) {
192- if (!strcmp (de -> d_name , "." ) ||
193- !strcmp (de -> d_name , ".." ))
194- continue ;
195- sp ++ ;
196- if (sp == LWS_ARRAY_SIZE (dir )) {
197- lwsl_err ("%s: Skipping too-deep subdir %s\n" ,
198- __func__ , filepath );
199- sp -- ;
200- continue ;
201- }
202- lws_strncpy (subdir [sp ], de -> d_name , sizeof (subdir [sp ]));
203- dir [sp ] = opendir (filepath );
204- if (!dir [sp ]) {
205- lwsl_err ("%s: Unable to open subdir '%s'\n" ,
206- __func__ , filepath );
207- goto bail ;
208- }
166+ if (S_ISDIR (s .st_mode ))
209167 continue ;
210- }
211- #endif
212168
213- m = strlen (filepath + initial ) + 1 ;
169+ m = strlen (de -> d_name ) + 1 ;
214170 dire = lwsac_use (& lwsac_head , sizeof (* dire ) + m , 0 );
215171 if (!dire ) {
216172 lwsac_free (& lwsac_head );
217-
218- goto bail ;
173+ closedir ( dir );
174+ return -1 ;
219175 }
220176
221177 dire -> next = NULL ;
222178 dire -> size = (unsigned long long )s .st_size ;
223179 dire -> mtime = s .st_mtime ;
224180 dire -> user [0 ] = '\0' ;
225- #if !defined(__COVERITY__ )
226- if (sp )
227- lws_strncpy (dire -> user , subdir [1 ], sizeof (dire -> user ));
228- #endif
229181
230- memcpy (& dire [1 ], filepath + initial , m );
182+ p_owner_end = strchr (de -> d_name , '_' );
183+ if (p_owner_end ) {
184+ size_t owner_len = (size_t )(p_owner_end - de -> d_name );
185+ if (owner_len < sizeof (dire -> user )) {
186+ memcpy (dire -> user , de -> d_name , owner_len );
187+ dire -> user [owner_len ] = '\0' ;
188+ }
189+ }
190+
191+ memcpy (& dire [1 ], de -> d_name , m );
231192
232193 lws_list_ptr_insert (& sorted_head , & dire -> next , de_mtime_sort );
233- } while (1 );
194+ }
195+
196+ closedir (dir );
234197
235198 /* the old lwsac continues to live while someone else is consuming it */
236199 if (vhd -> lwsac_head )
@@ -251,12 +214,6 @@ scan_upload_dir(struct vhd_deaddrop *vhd)
251214 } lws_end_foreach_llp (ppss , pss_list );
252215
253216 return 0 ;
254-
255- bail :
256- while (sp >= 0 )
257- closedir (dir [sp -- ]);
258-
259- return -1 ;
260217}
261218
262219static int
@@ -272,24 +229,22 @@ file_upload_cb(void *data, const char *name, const char *filename,
272229
273230 switch (state ) {
274231 case LWS_UFS_OPEN :
232+ /* Require an authenticated user to upload */
233+ if (!pss -> user [0 ]) {
234+ pss -> response_code = HTTP_STATUS_FORBIDDEN ;
235+ lwsl_warn ("%s: unauthenticated upload forbidden\n" ,
236+ __func__ );
237+ return -1 ;
238+ }
239+
275240 lws_urldecode (filename2 , filename , sizeof (filename2 ) - 1 );
276241 lws_filename_purify_inplace (filename2 );
277- if (pss -> user [0 ]) {
278- lws_filename_purify_inplace (pss -> user );
279- lws_snprintf (pss -> filename , sizeof (pss -> filename ),
280- "%s/%s" , pss -> vhd -> upload_dir , pss -> user );
281- if (mkdir (pss -> filename
282- #if !defined (WIN32 )
283- , 0700
284- #endif
285- ) < 0 )
286- lwsl_debug ("%s: mkdir failed\n" , __func__ );
287- lws_snprintf (pss -> filename , sizeof (pss -> filename ),
288- "%s/%s/%s~" , pss -> vhd -> upload_dir ,
289- pss -> user , filename2 );
290- } else
291- lws_snprintf (pss -> filename , sizeof (pss -> filename ),
292- "%s/%s~" , pss -> vhd -> upload_dir , filename2 );
242+ lws_filename_purify_inplace (pss -> user );
243+
244+ /* New filename format: upload_dir/user_originalfilename~ */
245+ lws_snprintf (pss -> filename , sizeof (pss -> filename ),
246+ "%s/%s_%s~" , pss -> vhd -> upload_dir ,
247+ pss -> user , filename2 );
293248 lwsl_notice ("%s: filename '%s'\n" , __func__ , pss -> filename );
294249
295250 pss -> fd = (lws_filefd_type )(long long )lws_open (pss -> filename ,
@@ -464,30 +419,31 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason,
464419 return 0 ;
465420
466421 case LWS_CALLBACK_RECEIVE :
467- /* we get this kind of thing {"del":"agreen/no-entry.svg "} */
422+ /* we get this kind of thing {"del":"user_agreen.txt "} */
468423 if (!pss || len < 10 )
469424 break ;
470425
471426 if (strncmp ((const char * )in , "{\"del\":\"" , 8 ))
472427 break ;
473428
474- /*
475- * NOTE: any authenticated user can delete any file.
476- * To restrict to owner, uncomment the following check.
477- */
478- // cp = strchr((const char *)in, '/');
479- // if (cp) {
480- // n = (int)(((uint8_t *)cp - (uint8_t *)in)) - 8;
481- //
482- // if ((int)strlen(pss->user) != n ||
483- // memcmp(pss->user, ((const char *)in) + 8, (unsigned int)n)) {
484- // lwsl_notice("%s: del: auth mismatch "
485- // " '%s' '%s' (%d)\n",
486- // __func__, pss->user,
487- // ((const char *)in) + 8, n);
488- // break;
489- // }
490- // }
429+ cp = strchr ((const char * )in + 8 , '_' );
430+ if (!cp ) {
431+ lwsl_warn ("%s: del: no owner in filename\n" , __func__ );
432+ break ;
433+ }
434+
435+ /* Check if the authenticated user matches the file owner prefix */
436+ n = (int )(cp - (((const char * )in ) + 8 ));
437+
438+ if ((int )strlen (pss -> user ) != n ||
439+ strncmp (pss -> user , ((const char * )in ) + 8 , (unsigned int )n )) {
440+ lwsl_notice ("%s: del: auth mismatch "
441+ " user '%s' tried to delete file with "
442+ "owner '%.*s'\n" ,
443+ __func__ , pss -> user , n ,
444+ ((const char * )in ) + 8 );
445+ break ;
446+ }
491447
492448 lws_strncpy (fname , ((const char * )in ) + 8 , sizeof (fname ));
493449 wp = strchr ((const char * )fname , '\"' );
0 commit comments