-
Notifications
You must be signed in to change notification settings - Fork 199
/
Copy pathmain.asm
512 lines (385 loc) · 9.46 KB
/
main.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
;Copyright (C) 2014 nemasu <[email protected]>
;
;This file is part of asmttpd.
;
;asmttpd is free software: you can redistribute it and/or modify
;it under the terms of the GNU General Public License as published by
;the Free Software Foundation, either version 2 of the License, or
;(at your option) any later version.
;
;asmttpd is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with asmttpd. If not, see <http://www.gnu.org/licenses/>.
%include "constants.asm"
%include "macros.asm"
%define ASMTTPD_VERSION "0.08"
%define LISTEN_PORT 0x5000 ; PORT 80, network byte order
%define THREAD_COUNT 10 ; Number of worker threads
;Follwing amd64 syscall standards for internal function calls: rdi rsi rdx r10 r8 r9
section .data
%include "data.asm"
section .bss
%include "bss.asm"
section .text
%include "string.asm"
%include "http.asm"
%include "syscall.asm"
;%include "mutex.asm"
;%include "debug.asm"
global _start
_start:
mov rdi, start_text
mov rsi, start_text_len
call print_line
mov rdi, [rsp] ;Num of args
cmp rdi,2 ;Exit if no argument, should be directory location
jne exit_with_help
mov rax, [rsp+16] ;Directory (first) parameter
mov [directory_path], rax
mov rdi, msg_using_directory
mov rsi, msg_using_directory_len
call sys_write
mov rdi, [directory_path]
call get_string_length
mov rsi, rax
call print_line
; Register signal handlers ( just close all other threads by jumping to SYS_EXIT_GROUP )
mov r10, 8 ; sizeof(sigset_t) displays 128, but strace shows 8 ... so 8 it is! -_-
xor rdx, rdx
mov rax, exit
mov [sa_handler], rax
mov rsi, sigaction
mov rdi, SIGINT
mov rax, SYS_RT_SIGACTION
syscall
mov rdi, SIGTERM
mov rax, SYS_RT_SIGACTION
syscall
;Try opening directory
mov rdi, [directory_path]
call sys_open_directory
cmp rax, 0
jl exit_with_no_directory_error
;Create socket
call sys_create_tcp_socket
cmp rax, 0
jl exit_error
mov [listen_socket], rax
;Bind to port 80
call sys_bind_server
cmp rax, 0
jl exit_error
;Start listening
call sys_listen
;Create threads
mov r10, THREAD_COUNT
thread_pool_setup:
push r10
mov rdi, worker_thread
xor rsi, rsi
call sys_clone
pop r10
dec r10
cmp r10, 0
jne thread_pool_setup
main_thread:
mov rdi, 10
call sys_sleep
jmp main_thread
worker_thread:
mov rbp, rsp
sub rsp, 24
mov QWORD [rbp-16], 0 ; Used for pointer to recieve buffer
mov rdi, THREAD_BUFFER_SIZE
call sys_mmap_mem
mov QWORD [rbp-16], rax
worker_thread_start:
call sys_accept
mov [rbp-8], rax ; save fd
mov rdi, rax
call sys_cork ; cork it
worker_thread_continue:
;HTTP Stuff starts here
mov rdi, QWORD [rbp-8] ;fd
mov rsi, [rbp-16] ;buffer
mov rdx, THREAD_BUFFER_SIZE ;size
call sys_recv
cmp rax, 0
jle worker_thread_close
;stackpush
;push rax
;mov rdi, rsi
;mov rsi, rax
;call print_line ; debug
;pop rax
;stackpop
; add null and save length
mov r11, rax ; save original received length
inc r11
mov rdi, [rbp-16]
add rdi, r11
mov BYTE [rdi], 0x00
;Make sure its a valid request
mov rdi, [rbp-16]
mov rsi, crlfx2
call string_ends_with
cmp rax, 1
jne worker_thread_close ; todo return 400
;Find request
mov rax, 0x2F ; '/' character
mov rdi, [rbp-16] ;scan buffer
mov rcx, -1 ;Start count
cld ;Increment rdi
repne scasb
jne worker_thread_close ;TODO: change to 400 error
mov rax, -2
sub rax, rcx ;Get the length
mov r8, rax ; start offset for requested file
mov rdi, [rbp-16]
add rdi, r8
mov rax, 0x20 ;'space' character
mov rcx, -1
cld
repne scasb
jne worker_thread_close ;TODO change to 400 error
mov rax, -1
sub rax, rcx
mov r9, rax
add r9, r8 ;end offset
;TODO: Assuming it's a file, need directory handling too
mov rdi, [rbp-16]
add rdi, r11 ; end of buffer, lets use it!
mov r12, r11 ; keeping count
mov rsi, [directory_path]
worker_thread_append_directory_path:
lodsb
stosb
inc r12
cmp rax, 0x00
jne worker_thread_append_directory_path
dec r12 ; get rid of 0x00
; Adds the file to the end of buffer ( where we juts put the document prefix )
mov rsi, [rbp-16]
add rsi, r8 ; points to beginning of path
mov rdi, [rbp-16]
add rdi, r12 ;go to end of buffer
mov rcx, r9
sub rcx, r8
add r12, rcx
rep movsb
dec r12 ; exclude space character
mov rdi, [rbp-16]
add rdi, r12
mov BYTE [rdi], 0x00 ; add null
mov r9, r11 ; saving offset into a stack saved register
; [rbp-16] + r9 now holds string for file opening
; Simple request logging
mov rdi, msg_request_log
mov rsi, msg_request_log_len
call sys_write
mov rdi, [rbp-16]
add rdi, r9
call get_string_length
mov rsi, rax
call print_line
;-----Simple logging
worker_thread_remove_pre_dir:
mov rdi, [rbp-16]
add rdi, r9
mov rsi, filter_prev_dir ; remove any '../'
call string_remove
cmp rax, 0
jne worker_thread_remove_pre_dir
mov rdi, [rbp-16]
add rdi, r9
call detect_content_type
mov r8, rax ;r8: Content Type
worker_thread_response:
;Try to open requested file
mov rdi, [rbp-16]
add rdi, r9
call sys_open
cmp rax, 0
jl worker_thread_404_response ;file not found, so 404
; Done with buffer offsets, put response and data into it starting at beg
mov r10, rax ; r10: file fd
;Determine if request requires a 206 response
mov rdi, r10 ; fd
call sys_get_file_size
push rax
;Basically if "Range:" is in the header
mov rdi, [rbp-16]
mov rsi, header_range_search
call string_contains
pop rdi
cmp rax, -1
jne worker_thread_206_response
jmp worker_thread_200_response ;else, we're good to go
;---------404 Response Start-------------
worker_thread_404_response:
mov rdi, [rbp-16]
call create_http404_response
;Send response
mov rdi, [rbp-8]
mov rsi, [rbp-16]
mov rdx, rax
call sys_send
;and exit
jmp worker_thread_close
;---------404 Response End--------------
;---------206 Response Start------------
worker_thread_206_response:
; r8: content type , r10: fd, rax: Range: start
push r10
push r8
mov r8, rdi ; r8 now size
;Seek to beg of file
mov rdi, r10 ; fd
mov rsi, 0
call sys_lseek
; find 'bytes='
mov rdi, [rbp-16]
add rdi, rax
mov rsi, find_bytes_range
call string_contains
cmp rax, -1
je worker_thread_close_file ; todo: send 400 response
add rdi, rax
add rdi, 6 ; go to number
push rdi ; save beg of first number
mov rax, 0
create_http206_response_lbeg:
inc rdi
inc rax
cmp rax, 200 ; todo tweak this number
jge worker_thread_close_file
cmp BYTE [rdi], 0x2D ; look for '-'
jne create_http206_response_lbeg
mov BYTE [rdi], 0x00 ; replace '-' with null
mov rbx, rdi ; save new beg
inc rbx
pop rdi ; restore beg of first number, convert to int
call string_atoi
mov rdi, rbx ; char after null
mov rbx, rax ; rbx: from byte range
push rdi ; save beginning of 2nd byte range
create_http206_response_rbeg:
inc rdi
cmp BYTE [rdi], 0x0a ; look for end of line
jne create_http206_response_rbeg
dec rdi
mov BYTE [rdi], 0x00; replace end with null
pop rdi ; restore 2nd byte range
call string_atoi
mov rcx,rax ; rcx: to byte range, -1 if there is no end
;byte range: rbx -> rcx(-1 if to end)
cmp rcx, -1
jne worker_thread_206_skip_unknown_end
mov rcx, r8
dec rcx ; zero based
worker_thread_206_skip_unknown_end:
cmp rcx, r8
jg worker_thread_close_file ; todo: change to 413 response
cmp rbx, rcx
jg worker_thread_close_file ; todo: change to 416 response
pop r9 ; type
mov r10, r8 ;total
mov rdi, [rbp-16]
mov rsi, rbx ;from
mov rdx, rcx ;to
call create_http206_response
mov r9, rax ; r9: header size
;Send it
mov rdi, [rbp-8]
mov rsi, [rbp-16]
mov rdx, r9
call sys_send
pop rdi ; fd
push rdi ; save it so we can close it
mov rsi, rbx
call sys_lseek
mov rsi, rdi
mov rdx, r8 ; size
mov rdi, [rbp-8]
call sys_sendfile
;stackpush
;push rax
;mov rdi, rsi
;mov rsi, r9
;call print_line ; debug
;pop rax
;stackpop
pop r10; restore fd for close
jmp worker_thread_close_file
;---------206 Response End--------------
;---------200 Response Start------------
worker_thread_200_response:
;rdi - total filesize
push rdi
;Seek to beg of file
mov rdi, r10 ; fd
mov rsi, 0
call sys_lseek
;Create Response
mov rdi, [rbp-16]
mov rsi, r8 ; type, figured out above
pop rdx ; total file size
push rdx ; save for sendfile
call create_http200_response
mov r8, rax ; header size
mov rdi, [rbp-8]
mov rsi, [rbp-16]
mov rdx, rax
call sys_send
cmp rax, 0
jle worker_thread_close_file
mov rdi, [rbp-8]
mov rsi, r10
pop rdx
call sys_sendfile
;---------200 Response End--------------
worker_thread_close_file:
;Uncork
mov rdi, [rbp-8]
call sys_uncork
;Close File
mov rdi, r10
call sys_close
;Close Socket
worker_thread_close:
mov rdi, [rbp-8]
call sys_close
jmp worker_thread_start
exit_with_no_directory_error:
mov rdi, msg_not_a_directory
mov rsi, msg_not_a_directory_len
call print_line
jmp exit
exit_with_help:
mov rdi, msg_help
mov rsi, msg_help_len
call print_line
jmp exit
exit_error:
mov rdi, msg_error
mov rsi, msg_error_len
call print_line
mov rdi, -1
mov rax, SYS_EXIT_GROUP
syscall
jmp exit
exit_thread:
xor rdi, rdi
mov rax, SYS_EXIT
syscall
jmp exit
exit:
mov rdi, [listen_socket]
call sys_close
xor rdi, rdi
mov rax, SYS_EXIT_GROUP
syscall