2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 * Written by Raphaël Gertz <rapsys@rapsys.eu>
18 //Required for mkostemp, O_CLOEXEC, strdup, memmem
21 //Required for SSIZE_MAX, LONG_MAX
24 //Required for pid_t, kill, waitpid
28 //Required for printf, sscanf, sprintf
31 //Required for struct stat, fstat
34 //Required for closedir, DIR, opendir, readdir, struct dirent
37 //Required for close, dup2, execve, fork, read, STDERR_FILENO, STDOUT_FILENO, STDIN_FILENO, write
40 //Required for open, O_CLOEXEC, O_NOATIME, O_NOFOLLOW
43 //Required for atoi, calloc, exit, EXIT_FAILURE, EXIT_SUCCESS, free, getenv, malloc, realloc
46 //Required for memchr, memcpy, memmem, strdup, strlen, strncmp
52 //Required for nanosleep
55 //Default passphrase max size
56 #define DEFAULT_PASSPHRASE_SIZE_MAX 512
58 //Default keyfile max size
59 //XXX: file should be maximum 8192*1024-1 character long
60 #define DEFAULT_KEYFILE_SIZE_MAX (8192 * 1024)
63 #define CRYPTTAB "/etc/crypttab"
66 #define CRYPTSETUP "/sbin/cryptsetup"
69 #define SYSTEMDCRYPTSETUP "/usr/lib/systemd/systemd-cryptsetup"
72 #define IHTTPDPID "/run/ihttpd/ihttpd.pid"
74 //Default systemd ask-password dir
75 #define ASKPASSWORDDIR "/run/systemd/ask-password"
78 #define ASKPASSWORDLOG "/run/ihttpd/log/child.askpassword.log"
79 #define IHTTPDLOG "/run/ihttpd/log/child.ihttpd.log"
81 //Create struct for http error status
82 struct httpStatusStruct
{
87 //Declare http error status array
88 const struct httpStatusStruct httpStatuses
[] = {
91 {405, "Method Not Allowed"},
92 {411, "Length Required"},
93 {500, "Internal Server Error"},
94 {503, "Service Unavailable"}
100 void die(const int, const char*);
101 void header(const int, const char*);
102 void showForm(const char*, const int, const int);
103 int extractValue(char**, int*, char*, int);
104 int extractLuksDevice(char**, char**);
105 int extractIHttpdPid(pid_t
*);
106 int extractAskPasswordPid(pid_t
*);
111 void die(const int code
, const char *err
) {
112 //TODO: see if we add a nice text/html template ?
113 //Send content as text
114 header(code
, "text/plain");
115 //Print error line if available
119 if (fflush(NULL
) == -1) {
122 //Exit with failure code
129 void header(const int code
, const char *ctype
) {
151 printf("Status: %d %s\r\n", httpStatuses
[k
].value
, httpStatuses
[k
].description
);
153 printf("Cache-Control: no-cache, no-store, must-revalidate\r\n");
154 printf("Pragma: no-cache\r\n");
155 printf("Expires: 0\r\n");
156 printf("X-Robots-Tag: noindex, nofollow, noarchive, nosnippet, noodp\r\n");
157 printf("Content-type: %s\r\n\r\n", ctype
);
163 void showForm(const char *requestUri
, const int keyfileSizeMax
, const int passphraseSizeMax
) {
164 header(503, "text/html");
165 printf("<!DOCTYPE HTML>\r\n");
166 printf("<html>\r\n");
167 printf("<head><title>Key upload form</title></head>\r\n");
168 printf("<body>\r\n");
169 printf("<div id=\"wrapper\">\r\n");
170 printf("<form enctype=\"multipart/form-data\" action=\"%s\" method=\"post\"><fieldset><legend>Upload key</legend><label for=\"file\"></label><input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"%d\" /><input id=\"file\" type=\"file\" name=\"key\" /><input type=\"submit\" value=\"Send\" /></fieldset></form>\r\n", requestUri
, keyfileSizeMax
);
171 printf("<form action=\"%s\" method=\"post\"><fieldset><legend>Type key</legend><label for=\"password\"></label><input id=\"password\" type=\"password\" name=\"key\" maxlength=\"%d\" /><input type=\"submit\" value=\"Send\" /></fieldset></form>\r\n", requestUri
, passphraseSizeMax
);
172 printf("</div>\r\n");
173 printf("</body>\r\n");
174 printf("</html>\r\n");
180 int extractValue(char **value
, int *valueLength
, char *contentType
, int contentLength
) {
181 //Handle application/x-www-form-urlencoded request
182 if (contentType
!= NULL
&& !strncmp(contentType
, "application/x-www-form-urlencoded", 33)) {
185 //Declare key and buf
188 if ((key
= malloc(4*sizeof(char))) == NULL
) {
189 //Unable to allocate key
192 //Allocate buf to maximum possible value size + 1 for trailing \0
193 if ((buf
= calloc(1, (DEFAULT_PASSPHRASE_SIZE_MAX
+1)*sizeof(char))) == NULL
) {
194 //Unable to allocate value
201 //XXX: initialised as & for new key, becomes = when fetching value
203 for (i
= 0, k
= 0, v
= 0; i
< contentLength
; i
++) {
204 //Safeguard against a value greater than DEFAULT_PASSPHRASE_SIZE_MAX
205 //XXX: this should never happen because we should be protected by contentLength already
206 if (v
== DEFAULT_PASSPHRASE_SIZE_MAX
+1) {
212 //Read one character from stdin
213 r
= read(STDIN_FILENO
, &d
, 1);
216 //Error while parsing post data
226 //Handle case where key has an other name
228 //Check key is "key" and we get '=' as new char and assign delim to =
229 if (strncmp(key
, "key", 3) || (delim
= d
) != '=') {
235 //Handle key or value separator in query string
236 } else if (d
== '&' || d
== '=') {
237 //Invalid query string
256 //Unescape and reduce value if not empty
260 //Loop on value and reduce length on the fly
261 for(l
=0,m
=0; m
< v
; l
++,m
++) {
262 //Replace + with space
265 //Skip partial present %XX
268 (buf
[l
] = buf
[m
]) == '%' &&
269 //Check we didn't reach valueStrLength
271 //Check next two digits are valid
272 ((buf
[m
+1] >= 'A' && buf
[m
+1] <= 'F') || (buf
[m
+1] >= 'a' && buf
[m
+1] <= 'f') || (buf
[m
+1] >= '0' && buf
[m
+1] <= '9')) &&
273 ((buf
[m
+2] >= 'A' && buf
[m
+2] <= 'F') || (buf
[m
+2] >= 'a' && buf
[m
+2] <= 'f') || (buf
[m
+2] >= '0' && buf
[m
+2] <= '9'))
275 buf
[l
] = (buf
[m
+1] >= 'A' ? (buf
[m
+1] & 0xdf) - 'A' + 10 : buf
[m
+1] - '0') * 16 + (buf
[m
+2] >= 'A' ? (buf
[m
+2] & 0xdf) - 'A' + 10 : buf
[m
+2] - '0');
283 if ((*value
= malloc((*valueLength
)*sizeof(char))) == NULL
) {
284 //Unable to alloc value
290 memcpy(*value
, buf
, *valueLength
);
294 //Handle multipart/form-data request
295 } else if (contentType
!= NULL
&& !strncmp(contentType
, "multipart/form-data", 19)) {
299 int boundaryLength
= strlen(contentType
) - 30 + 1;
300 //Client send LF ending without CR
305 if ((boundary
= calloc(1, boundaryLength
*sizeof(char))) == NULL
) {
306 //Unable to allocate boundary
310 memcpy(boundary
, contentType
+ 30, boundaryLength
- 1);
315 if ((buf
= malloc(contentLength
*sizeof(char))) == NULL
) {
316 //Unable to allocate buffer
324 for (b
= 0, s
= 0; b
< contentLength
; b
++) {
325 //Detect possible boundary
326 //XXX: b is boundaryLength-1 + 2 after s
327 //XXX: d will be a CR(CRLF line ending) or LF(LF line ending) or -(of final --)
328 if (b
== s
+ 2 + boundaryLength
- 1 && !strncmp(boundary
, buf
+ b
- boundaryLength
+ 1, boundaryLength
- 1)) {
329 //Only after first boundary match
332 if (start
[0] == '\r' && start
[1] == '\n') {
335 } else if (start
[0] == '\n') {
341 char *new = start
, *prev
= start
, *name
= NULL
;
342 //Search for a new line
343 while ((new = memchr(new, '\n', b
- (new - buf
)))) {
344 //Jump to first character after new line
347 int lineLength
= new - prev
- 1;
348 //Remove chariage return if necessary
349 if (prev
[lineLength
] == '\r') {
353 //Break loop after headers end
354 if (lineLength
== 1) {
357 //Allocate a name buf of maximum line length
358 //XXX: need to be filled with zero as we don't know what will comes with sscanf call and we rely on strlen
359 if ((name
= calloc(1, lineLength
*sizeof(char))) == NULL
) {
360 //Unable to allocate name
366 if (sscanf(prev
, "Content-Disposition: form-data; name=\"%[^\"]\"", name
)) {
368 if ((name
= realloc(name
, (strlen(name
)+1)*sizeof(char))) == NULL
) {
369 //Unable to reduce name
375 if (!strncmp(name
, "key", 3)) {
384 //Init value if found
387 char *end
= buf
+ b
- boundaryLength
- 3;
388 //Remove CR at end if provided
389 //XXX: only remove CR at end if we encountered one before
394 if (end
- new - 1 >= DEFAULT_KEYFILE_SIZE_MAX
) {
403 *valueLength
= end
- new - 1;
405 if ((*value
= malloc((*valueLength
)*sizeof(char))) == NULL
) {
406 //Unable to allocate value
412 memcpy(*value
, new, *valueLength
);
416 //Set start to matched boundary
419 //Read one character from stdin
420 r
= read(STDIN_FILENO
, &d
, 1);
423 //Error while parsing post data
435 //Store new possible boundary start
454 * Extract luks and device
456 int extractLuksDevice(char **luks
, char **device
) {
457 //Declare file descriptor
459 //Declare buf, device and luks pointer
461 //Declare stat struct
464 if ((fd
= open(CRYPTTAB
, O_RDONLY
|O_NOATIME
|O_NOFOLLOW
|O_CLOEXEC
)) == -1) {
465 //Can't open crypttab file
469 if ((stats
= calloc(1, sizeof(struct stat
))) == NULL
) {
470 //Unable to allocate stats
474 if (fstat(fd
, stats
) == -1) {
475 //Can't stat crypttab
479 if ((bufLength
= stats
->st_size
) > SSIZE_MAX
) {
484 if ((buf
= malloc(bufLength
*sizeof(char))) == NULL
) {
485 //Unable to allocate buf
489 if ((read(fd
, buf
, bufLength
)) < bufLength
) {
490 //Fail to read crypttab file
498 //Search first separator (\s|\t) after luks
499 if ((l
= memchr(buf
, ' ', bufLength
)) == NULL
&& (l
= memchr(buf
, ' ', bufLength
)) == NULL
) {
504 //Search first separator (\s|\t) after device
505 if ((d
= memchr(l
, ' ', bufLength
- (l
- buf
))) == NULL
&& (d
= memchr(l
, ' ', bufLength
- (l
- buf
))) == NULL
&& (d
= memchr(l
, '\n', bufLength
- (l
- buf
))) == NULL
) {
512 if ((*luks
= malloc((l
- buf
- 1)*sizeof(char))) == NULL
) {
516 if ((*device
= malloc((d
- l
- 1)*sizeof(char))) == NULL
) {
517 //Free and reset luks
524 memcpy(*luks
, buf
, l
- buf
- 1);
526 (*luks
)[l
- buf
- 1] = '\0';
529 memcpy(*device
, l
, d
- l
- 1);
531 (*device
)[d
- l
- 1] = '\0';
541 * Extract ask-password pid
543 int extractAskPasswordPid(pid_t
*pid
) {
544 //Declare stuct dirent
545 struct dirent
*entry
;
551 //Allocate dirent struct
552 if ((entry
= calloc(1, sizeof(struct dirent
))) == NULL
) {
553 //Unable to allocate entry
557 //Open systemd ask-password dir
558 if ((askdir
= opendir(ASKPASSWORDDIR
)) == NULL
) {
564 if (chdir(ASKPASSWORDDIR
) == -1) {
565 //Can't change to ask dir
569 //Loop on dir content
570 while((entry
= readdir(askdir
))) {
571 //Handle each ask.XXXXXX file
572 if (!strncmp(entry
->d_name
, "ask.", 4) && strlen(entry
->d_name
) == 10) {
573 //Declare file descriptor
577 //Declare stat struct
580 if ((fd
= open(entry
->d_name
, O_RDONLY
|O_NOATIME
|O_NOFOLLOW
|O_CLOEXEC
)) == -1) {
581 //Can't open ask file
585 if ((stats
= calloc(1, sizeof(struct stat
))) == NULL
) {
586 //Unable to allocate stats
590 if (fstat(fd
, stats
) == -1) {
591 //Can't stat ask file
595 if ((bufLength
= stats
->st_size
) > SSIZE_MAX
) {
600 if ((buf
= malloc(bufLength
*sizeof(char))) == NULL
) {
601 //Unable to allocate buf
605 if ((read(fd
, buf
, bufLength
)) < bufLength
) {
606 //Fail to read ask file
615 char *nl
= buf
, *pl
= buf
, *e
;
619 //Search for a new line
620 while ((nl
= memmem(nl
, bufLength
- (nl
- buf
), "\n", strlen("\n")))) {
624 //Check if we have a = in line but not empty value ("=\n")
625 if ((e
= memmem(pl
, bufLength
- (pl
- buf
), "=", strlen("="))) && e
< nl
- 2) {
629 if (!strncmp(pl
, "PID", 3)) {
632 //Allocate pid string
633 if ((pidStr
= malloc((nl
- e
)*sizeof(char))) == NULL
) {
634 //Unable to allocate pid string
638 memcpy(pidStr
, e
, nl
- e
- 1);
639 //Terminate pid string
640 pidStr
[nl
- e
] = '\0';
642 if ((*pid
= atoi(pidStr
)) <= 1) {
648 //Found a valid process
653 //Jump prev line to new line
662 //Close systemd ask-password dir
663 if (closedir(askdir
) == -1) {
664 //Can't close ask dir
675 //Found more than one pid
676 } else if (found
> 1) {
688 int extractIHttpdPid(pid_t
*pid
) {
689 //Declare file descriptor
691 //Declare buf, device and luks pointer
692 char *buf
, *l
, *pidStr
;
693 //Declare stat struct
696 if ((fd
= open(IHTTPDPID
, O_RDONLY
|O_NOATIME
|O_NOFOLLOW
|O_CLOEXEC
)) == -1) {
697 //Can't open crypttab file
701 if ((stats
= calloc(1, sizeof(struct stat
))) == NULL
) {
702 //Unable to allocate stats
706 if (fstat(fd
, stats
) == -1) {
707 //Can't stat crypttab
711 if ((bufLength
= stats
->st_size
) > SSIZE_MAX
) {
716 if ((buf
= malloc(bufLength
*sizeof(char))) == NULL
) {
717 //Unable to allocate buf
721 if ((read(fd
, buf
, bufLength
)) < bufLength
) {
722 //Fail to read crypttab file
730 //Search first separator (\s|\t|\n) after pid
731 if ((l
= memchr(buf
, ' ', bufLength
)) == NULL
&& (l
= memchr(buf
, ' ', bufLength
)) == NULL
&& (l
= memchr(buf
, '\n', bufLength
)) == NULL
) {
738 if ((pidStr
= malloc((l
- buf
- 1)*sizeof(char))) == NULL
) {
743 memcpy(pidStr
, buf
, l
- buf
- 1);
745 pidStr
[l
- buf
- 1] = '\0';
751 if ((*pid
= atoi(pidStr
)) <= 1) {
766 int main(int argc
, char **argv
) {
768 char *requestMethod
= getenv("REQUEST_METHOD");
770 //Handle unknown requests
771 if (requestMethod
== NULL
|| (strncmp(requestMethod
, "GET", 3) && strncmp(requestMethod
, "HEAD", 4) && strncmp(requestMethod
, "POST", 4))) {
772 //Send method not allowed
773 die(405, "Unsupported request method");
774 //Handle get and head
775 } else if (!strncmp(requestMethod
, "GET", 3) || !strncmp(requestMethod
, "HEAD", 4)) {
777 showForm(getenv("REQUEST_URI")?getenv("REQUEST_URI"):"/", DEFAULT_KEYFILE_SIZE_MAX
, DEFAULT_PASSPHRASE_SIZE_MAX
);
779 } else /*if (!strncmp(requestMethod, "POST", 4))*/ {
787 //XXX: will contain number of char in value without trailing \0
790 //XXX: will contain value without a tailing \0
795 //Content length string from env
796 char *contentLengthStr
= getenv("CONTENT_LENGTH");
798 char *contentType
= getenv("CONTENT_TYPE");
800 //Declare luks and device
801 char *luks
= NULL
, *device
= NULL
;
806 //Pairs of pipe for stdin, stdout and stderr
807 int inPipe
[2], errPipe
[2];
809 //Handle unknown content type
810 if (contentType
== NULL
|| (strncmp(contentType
, "application/x-www-form-urlencoded", 33) && strncmp(contentType
, "multipart/form-data", 19))) {
811 die(400, "Unknown content type");
814 //Handle invalid multipart/form-data content type
815 //XXX: max boundary length is 70 as per rfc1521 & rfc2046
816 if (!strncmp(contentType
, "multipart/form-data", 19) && (strncmp(contentType
, "multipart/form-data; boundary=", 30) || strlen(contentType
) <= 30 || strlen(contentType
) > 100)) {
817 die(400, "Malformed boundary in multipart/form-data request");
820 //Handle invalid content length
821 //XXX: deny empty contentLength as chrome send a contentLength even for a device
822 if (contentLengthStr
== NULL
|| (contentLength
= atoi(contentLengthStr
)) <= 0) {
823 die(411, "Invalid content length");
826 //Handle application/x-www-form-urlencoded request length
827 //XXX: limit to key=xyz where xyz can be all encoded in %XX
828 if (!strncmp(contentType
, "application/x-www-form-urlencoded", 33) && contentLength
> (DEFAULT_PASSPHRASE_SIZE_MAX
* 3 + 4)) {
829 die(400, "Invalid application/x-www-form-urlencoded request length");
832 //Handle multipart/form-data request length
833 //XXX: limit to arbitrary 3 times the keyfile max size
834 if (!strncmp(contentType
, "multipart/form-data", 19) && contentLength
> (DEFAULT_KEYFILE_SIZE_MAX
* 3)) {
835 die(400, "Invalid multipart/form-data request length");
839 if ((ret
= extractValue(&value
, &valueLength
, contentType
, contentLength
)) < 0) {
840 die(500, "Failed to extract value");
843 //Extract luks and device
844 if ((ret
= extractLuksDevice(&luks
, &device
)) < 0) {
845 die(500, "Failed to extract luks and device");
848 //Declare cargv array
849 char *cargvs
[] = { CRYPTSETUP
, "-d", "-", "luksOpen", device
, luks
, NULL
};
850 //TODO: device cannot be an UUID=xyz, a resolved block device is required for it
851 char *scargvs
[] = { SYSTEMDCRYPTSETUP
, "attach", luks
, device
, "-", NULL
};
853 //Check cryptsetup binary
854 if (access(CRYPTSETUP
, F_OK
|X_OK
) == -1) {
855 //Check systemdcryptsetup binary
856 if (access(SYSTEMDCRYPTSETUP
, F_OK
|X_OK
) == -1) {
857 die(500, "No cryptsetup available");
860 //TODO: resolve UUID in real device name
861 //TODO: passing password through the socket is not possible, as it rely on password ending with \0
862 die(500, "systemd-cryptsetupd is not implementable");
870 if (pipe(inPipe
) == -1) {
871 die(500, "Failed to create in pipe");
875 if (pipe(errPipe
) == -1) {
876 die(500, "Failed to create err pipe");
880 if ((pid
= fork()) == -1) {
881 die(500, "Failed to fork");
887 char *carge
[] = { NULL
};
890 //Redirect stdin to pipe
891 if (dup2(inPipe
[0], STDIN_FILENO
) == -1) {
892 die(500, "Failed to redirect in pipe");
897 //Redirect stderr to pipe
898 if (dup2(errPipe
[1], STDERR_FILENO
) == -1) {
899 die(500, "Failed to redirect err pipe");
906 if (execve(cargv
[0], cargv
, carge
) == -1) {
907 die(500, "Failed to call cryptsetup");
916 //Close unused inPipe end
918 //Close unused errPipe end
921 //Send password on stdin anyway
922 //XXX: this fail if device is already unlocked for example
923 write(inPipe
[1], value
, valueLength
);
928 //Close stdin with EOF
932 if (waitpid(pid
, &ret
, 0) == -1) {
933 die(500, "Failed to wait child");
936 //Handle already in use device
938 die(500, "Device already in use");
939 //Handle already unlocked device
940 //} else if (ret == 1280) {
941 // die(200, "Device already unlocked");
942 //Handle invalid luks device
943 //} else if (ret == 256) {
944 // die(500, "Device is now a valid device");
945 //Handle no key available with this passphrase
946 } else if (ret
== 512) {
947 die(500, "No slot for this value");
948 //Handle unexisting device or permission denied
949 } else if (ret
== 1014) {
950 die(500, "Device doesn't exist or access denied");
952 } else if (ret
!= 0) {
953 //Err length and counter
954 int errLength
= 2048, e
= 0;
960 if ((err
= malloc(errLength
*sizeof(char))) == NULL
) {
961 die(500, "Couldn't alloc err buffer");
963 //Advance after ret code
964 e
= sprintf(err
, "%d:", ret
);
965 //Fetch stderr and store in err buffer
966 while(read(errPipe
[0], &c
, 1) > 0) {
967 //Grow buffer if we reach end
968 if (e
== errLength
) {
969 if ((err
= realloc(err
, (errLength
+2048)*sizeof(char))) == NULL
) {
970 die(500, "Couldn't grow err buffer");
979 //Terminate err buffer
982 if ((err
= realloc(err
, (e
+1)*sizeof(char))) == NULL
) {
983 die(500, "Couldn't ungrow err buffer");
985 //Die with luks error
992 //Removed as it was making fail the process of booting sometimes
995 if ((pid
= fork()) == -1) {
996 die(500, "Failed to fork");
999 //IHttpd killing child process
1004 //Declare ihttpd pid
1008 close(STDIN_FILENO
);
1010 //Disable line buffering on stdout and stderr
1011 setvbuf(stdout
, NULL
, _IONBF
, 0);
1012 setvbuf(stderr
, NULL
, _IONBF
, 0);
1014 //Redirect output to log
1015 if ((fd
= open(IHTTPDLOG
, O_CREAT
| O_TRUNC
| O_WRONLY
, S_IRUSR
| S_IWUSR
)) == -1) {
1016 fprintf(stderr
, "Open ihttpd child log failed\n");
1019 close(STDOUT_FILENO
);
1020 //Redirect stdout on childlog
1021 if (dup2(fd
, STDOUT_FILENO
) == -1) {
1022 fprintf(stderr
, "Redirect stdout to ihttpd child log failed\n");
1025 close(STDERR_FILENO
);
1026 //Redirect stderr on childlog
1027 if (dup2(fd
, STDERR_FILENO
) == -1) {
1028 fprintf(stderr
, "Redirect stderr to ihttpd child log failed\n");
1034 //Extract ihttpd pid
1035 if (extractIHttpdPid(&ihttpdPid
) < 0) {
1036 fprintf(stderr
, "Failed to extract ihttpd pid");
1040 //Close stdout and stderr without childlog
1042 close(STDOUT_FILENO
);
1043 close(STDERR_FILENO
);
1046 //Wait until get rattached to init(getppid()==1)
1047 //XXX: we are really blind here
1048 while(getppid() != 1) {
1049 //Sleep half a second
1050 if (usleep(500000) == -1 && fd
!= -1) {
1051 printf("Usleep failed\n");
1056 if (kill(ihttpdPid
, 0) == 0 && kill(ihttpdPid
, SIGTERM
) == -1 && fd
!= -1) {
1057 printf("Termiate ihttpd failed\n");
1060 //Sleep half a second
1061 if (usleep(500000) == -1 && fd
!= -1) {
1062 printf("Usleep failed\n");
1066 if (kill(ihttpdPid
, 0) == 0 && kill(ihttpdPid
, SIGKILL
) == -1) {
1067 printf("Kill ihttpd failed\n");
1074 //Sleep before killing askpassword process
1075 if (usleep(500000) == -1) {
1076 die(500, "Usleep failed");
1080 if ((pid
= fork()) == -1) {
1081 die(500, "Failed to fork");
1084 //Ask password killing child process
1085 //XXX: we are blind here
1090 //Declare ask password pid
1091 pid_t askPasswordPid
;
1094 close(STDIN_FILENO
);
1096 //Disable line buffering on stdout and stderr
1097 setvbuf(stdout
, NULL
, _IONBF
, 0);
1098 setvbuf(stderr
, NULL
, _IONBF
, 0);
1100 //Redirect output to log
1101 if ((fd
= open(ASKPASSWORDLOG
, O_CREAT
| O_TRUNC
| O_WRONLY
, S_IRUSR
| S_IWUSR
)) == -1) {
1102 fprintf(stderr
, "Open ask password child log failed\n");
1105 close(STDOUT_FILENO
);
1106 //Redirect stdout on childlog
1107 if (dup2(fd
, STDOUT_FILENO
) == -1) {
1108 fprintf(stderr
, "Redirect stdout to ask password child log failed\n");
1111 close(STDERR_FILENO
);
1112 //Redirect stderr on childlog
1113 if (dup2(fd
, STDERR_FILENO
) == -1) {
1114 fprintf(stderr
, "Redirect stderr to ask password child log failed\n");
1120 //Extract ask password pid
1121 if (extractAskPasswordPid(&askPasswordPid
) < 0) {
1122 fprintf(stderr
, "Failed to extract ask password pid");
1126 //Close stdout and stderr without childlog
1128 close(STDOUT_FILENO
);
1129 close(STDERR_FILENO
);
1132 //Wait until get rattached to init(getppid()==1)
1133 //XXX: we are really blind here
1134 while(getppid() != 1) {
1135 //Sleep half a second
1136 if (usleep(500000) == -1 && fd
!= -1) {
1137 printf("Usleep failed\n");
1141 //Termitate ask password
1142 if (kill(askPasswordPid
, 0) == 0 && kill(askPasswordPid
, SIGTERM
) == -1 && fd
!= -1) {
1143 printf("Termiate ask password failed\n");
1147 //Sleep half a second
1148 if (usleep(500000) == -1 && fd
!= -1) {
1149 printf("Usleep failed\n");
1153 if (kill(askPasswordPid
, 0) == 0 && kill(askPasswordPid
, SIGKILL
) == -1) {
1154 printf("Kill ask password failed\n");
1161 header(200, "text/plain");
1162 printf("Sent value, boot should resume now");