dbutil.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /*
  2. * Dropbear - a SSH2 server
  3. *
  4. * Copyright (c) 2002,2003 Matt Johnston
  5. * All rights reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. *
  25. * strlcat() is copyright as follows:
  26. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  27. * All rights reserved.
  28. *
  29. * Redistribution and use in source and binary forms, with or without
  30. * modification, are permitted provided that the following conditions
  31. * are met:
  32. * 1. Redistributions of source code must retain the above copyright
  33. * notice, this list of conditions and the following disclaimer.
  34. * 2. Redistributions in binary form must reproduce the above copyright
  35. * notice, this list of conditions and the following disclaimer in the
  36. * documentation and/or other materials provided with the distribution.
  37. * 3. The name of the author may not be used to endorse or promote products
  38. * derived from this software without specific prior written permission.
  39. *
  40. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  41. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  42. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  43. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  44. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  45. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  46. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  47. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  48. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  49. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
  50. #include "config.h"
  51. #ifdef __linux__
  52. #define _GNU_SOURCE
  53. /* To call clock_gettime() directly */
  54. #include <sys/syscall.h>
  55. #endif /* __linux */
  56. #ifdef HAVE_MACH_MACH_TIME_H
  57. #include <mach/mach_time.h>
  58. #include <mach/mach.h>
  59. #endif
  60. #include "includes.h"
  61. #include "dbutil.h"
  62. #include "buffer.h"
  63. #include "session.h"
  64. #include "atomicio.h"
  65. #define MAX_FMT 100
  66. static void generic_dropbear_exit(int exitcode, const char* format,
  67. va_list param) ATTRIB_NORETURN;
  68. static void generic_dropbear_log(int priority, const char* format,
  69. va_list param);
  70. void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_NORETURN
  71. = generic_dropbear_exit;
  72. void (*_dropbear_log)(int priority, const char* format, va_list param)
  73. = generic_dropbear_log;
  74. #if DEBUG_TRACE
  75. int debug_trace = 0;
  76. #endif
  77. #ifndef DISABLE_SYSLOG
  78. void startsyslog(const char *ident) {
  79. openlog(ident, LOG_PID, LOG_AUTHPRIV);
  80. }
  81. #endif /* DISABLE_SYSLOG */
  82. /* the "format" string must be <= 100 characters */
  83. void dropbear_close(const char* format, ...) {
  84. va_list param;
  85. va_start(param, format);
  86. _dropbear_exit(EXIT_SUCCESS, format, param);
  87. va_end(param);
  88. }
  89. void dropbear_exit(const char* format, ...) {
  90. va_list param;
  91. va_start(param, format);
  92. _dropbear_exit(EXIT_FAILURE, format, param);
  93. va_end(param);
  94. }
  95. static void generic_dropbear_exit(int exitcode, const char* format,
  96. va_list param) {
  97. char fmtbuf[300];
  98. snprintf(fmtbuf, sizeof(fmtbuf), "Exited: %s", format);
  99. _dropbear_log(LOG_INFO, fmtbuf, param);
  100. #if DROPBEAR_FUZZ
  101. if (fuzz.do_jmp) {
  102. longjmp(fuzz.jmp, 1);
  103. }
  104. #endif
  105. exit(exitcode);
  106. }
  107. void fail_assert(const char* expr, const char* file, int line) {
  108. dropbear_exit("Failed assertion (%s:%d): `%s'", file, line, expr);
  109. }
  110. static void generic_dropbear_log(int UNUSED(priority), const char* format,
  111. va_list param) {
  112. char printbuf[1024];
  113. vsnprintf(printbuf, sizeof(printbuf), format, param);
  114. fprintf(stderr, "%s\n", printbuf);
  115. }
  116. /* this is what can be called to write arbitrary log messages */
  117. void dropbear_log(int priority, const char* format, ...) {
  118. va_list param;
  119. va_start(param, format);
  120. _dropbear_log(priority, format, param);
  121. va_end(param);
  122. }
  123. #if DEBUG_TRACE
  124. static double debug_start_time = -1;
  125. void debug_start_net()
  126. {
  127. if (getenv("DROPBEAR_DEBUG_NET_TIMESTAMP"))
  128. {
  129. /* Timestamps start from first network activity */
  130. struct timeval tv;
  131. gettimeofday(&tv, NULL);
  132. debug_start_time = tv.tv_sec + (tv.tv_usec / 1000000.0);
  133. TRACE(("Resetting Dropbear TRACE timestamps"))
  134. }
  135. }
  136. static double time_since_start()
  137. {
  138. double nowf;
  139. struct timeval tv;
  140. gettimeofday(&tv, NULL);
  141. nowf = tv.tv_sec + (tv.tv_usec / 1000000.0);
  142. if (debug_start_time < 0)
  143. {
  144. debug_start_time = nowf;
  145. return 0;
  146. }
  147. return nowf - debug_start_time;
  148. }
  149. static void dropbear_tracelevel(int level, const char *format, va_list param)
  150. {
  151. if (debug_trace == 0 || debug_trace < level) {
  152. return;
  153. }
  154. fprintf(stderr, "TRACE%d (%d) %f: ", level, getpid(), time_since_start());
  155. vfprintf(stderr, format, param);
  156. fprintf(stderr, "\n");
  157. }
  158. #if (DEBUG_TRACE>=1)
  159. void dropbear_trace1(const char* format, ...) {
  160. va_list param;
  161. va_start(param, format);
  162. dropbear_tracelevel(1, format, param);
  163. va_end(param);
  164. }
  165. #endif
  166. #if (DEBUG_TRACE>=2)
  167. void dropbear_trace2(const char* format, ...) {
  168. va_list param;
  169. va_start(param, format);
  170. dropbear_tracelevel(2, format, param);
  171. va_end(param);
  172. }
  173. #endif
  174. #if (DEBUG_TRACE>=3)
  175. void dropbear_trace3(const char* format, ...) {
  176. va_list param;
  177. va_start(param, format);
  178. dropbear_tracelevel(3, format, param);
  179. va_end(param);
  180. }
  181. #endif
  182. #if (DEBUG_TRACE>=4)
  183. void dropbear_trace4(const char* format, ...) {
  184. va_list param;
  185. va_start(param, format);
  186. dropbear_tracelevel(4, format, param);
  187. va_end(param);
  188. }
  189. #endif
  190. #if (DEBUG_TRACE>=5)
  191. void dropbear_trace5(const char* format, ...) {
  192. va_list param;
  193. va_start(param, format);
  194. dropbear_tracelevel(5, format, param);
  195. va_end(param);
  196. }
  197. #endif
  198. #endif
  199. /* Connect to a given unix socket. The socket is blocking */
  200. #if ENABLE_CONNECT_UNIX
  201. int connect_unix(const char* path) {
  202. struct sockaddr_un addr;
  203. int fd = -1;
  204. memset((void*)&addr, 0x0, sizeof(addr));
  205. addr.sun_family = AF_UNIX;
  206. strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
  207. fd = socket(PF_UNIX, SOCK_STREAM, 0);
  208. if (fd < 0) {
  209. TRACE(("Failed to open unix socket"))
  210. return -1;
  211. }
  212. if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
  213. TRACE(("Failed to connect to '%s' socket", path))
  214. m_close(fd);
  215. return -1;
  216. }
  217. return fd;
  218. }
  219. #endif
  220. /* Sets up a pipe for a, returning three non-blocking file descriptors
  221. * and the pid. exec_fn is the function that will actually execute the child process,
  222. * it will be run after the child has fork()ed, and is passed exec_data.
  223. * If ret_errfd == NULL then stderr will not be captured.
  224. * ret_pid can be passed as NULL to discard the pid. */
  225. int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
  226. int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
  227. int infds[2];
  228. int outfds[2];
  229. int errfds[2];
  230. pid_t pid;
  231. const int FDIN = 0;
  232. const int FDOUT = 1;
  233. #if DROPBEAR_FUZZ
  234. if (fuzz.fuzzing) {
  235. return fuzz_spawn_command(ret_writefd, ret_readfd, ret_errfd, ret_pid);
  236. }
  237. #endif
  238. /* redirect stdin/stdout/stderr */
  239. if (pipe(infds) != 0) {
  240. return DROPBEAR_FAILURE;
  241. }
  242. if (pipe(outfds) != 0) {
  243. return DROPBEAR_FAILURE;
  244. }
  245. if (ret_errfd && pipe(errfds) != 0) {
  246. return DROPBEAR_FAILURE;
  247. }
  248. #if DROPBEAR_VFORK
  249. pid = vfork();
  250. #else
  251. pid = fork();
  252. #endif
  253. if (pid < 0) {
  254. return DROPBEAR_FAILURE;
  255. }
  256. if (!pid) {
  257. /* child */
  258. TRACE(("back to normal sigchld"))
  259. /* Revert to normal sigchld handling */
  260. if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
  261. dropbear_exit("signal() error");
  262. }
  263. /* redirect stdin/stdout */
  264. if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
  265. (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
  266. (ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
  267. TRACE(("leave noptycommand: error redirecting FDs"))
  268. dropbear_exit("Child dup2() failure");
  269. }
  270. close(infds[FDOUT]);
  271. close(infds[FDIN]);
  272. close(outfds[FDIN]);
  273. close(outfds[FDOUT]);
  274. if (ret_errfd)
  275. {
  276. close(errfds[FDIN]);
  277. close(errfds[FDOUT]);
  278. }
  279. exec_fn(exec_data);
  280. /* not reached */
  281. return DROPBEAR_FAILURE;
  282. } else {
  283. /* parent */
  284. close(infds[FDIN]);
  285. close(outfds[FDOUT]);
  286. setnonblocking(outfds[FDIN]);
  287. setnonblocking(infds[FDOUT]);
  288. if (ret_errfd) {
  289. close(errfds[FDOUT]);
  290. setnonblocking(errfds[FDIN]);
  291. }
  292. if (ret_pid) {
  293. *ret_pid = pid;
  294. }
  295. *ret_writefd = infds[FDOUT];
  296. *ret_readfd = outfds[FDIN];
  297. if (ret_errfd) {
  298. *ret_errfd = errfds[FDIN];
  299. }
  300. return DROPBEAR_SUCCESS;
  301. }
  302. }
  303. /* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and
  304. * re-enabled SIGPIPE. If cmd is NULL, will run a login shell.
  305. */
  306. void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
  307. char * argv[4];
  308. char * baseshell = NULL;
  309. unsigned int i;
  310. baseshell = basename(usershell);
  311. if (cmd != NULL) {
  312. argv[0] = baseshell;
  313. } else {
  314. /* a login shell should be "-bash" for "/bin/bash" etc */
  315. int len = strlen(baseshell) + 2; /* 2 for "-" */
  316. argv[0] = (char*)m_malloc(len);
  317. snprintf(argv[0], len, "-%s", baseshell);
  318. }
  319. if (cmd != NULL) {
  320. argv[1] = "-c";
  321. argv[2] = (char*)cmd;
  322. argv[3] = NULL;
  323. } else {
  324. /* construct a shell of the form "-bash" etc */
  325. argv[1] = NULL;
  326. }
  327. /* Re-enable SIGPIPE for the executed process */
  328. if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
  329. dropbear_exit("signal() error");
  330. }
  331. /* close file descriptors except stdin/stdout/stderr
  332. * Need to be sure FDs are closed here to avoid reading files as root */
  333. for (i = 3; i <= maxfd; i++) {
  334. m_close(i);
  335. }
  336. execv(usershell, argv);
  337. }
  338. #if DEBUG_TRACE
  339. void printhex(const char * label, const unsigned char * buf, int len) {
  340. int i, j;
  341. fprintf(stderr, "%s\n", label);
  342. /* for each 16 byte line */
  343. for (j = 0; j < len; j += 16) {
  344. const int linelen = MIN(16, len - j);
  345. /* print hex digits */
  346. for (i = 0; i < 16; i++) {
  347. if (i < linelen) {
  348. fprintf(stderr, "%02x", buf[j+i]);
  349. } else {
  350. fprintf(stderr, " ");
  351. }
  352. // separator between pairs
  353. if (i % 2 ==1) {
  354. fprintf(stderr, " ");
  355. }
  356. }
  357. /* print characters */
  358. fprintf(stderr, " ");
  359. for (i = 0; i < linelen; i++) {
  360. char c = buf[j+i];
  361. if (!isprint(c)) {
  362. c = '.';
  363. }
  364. fputc(c, stderr);
  365. }
  366. fprintf(stderr, "\n");
  367. }
  368. }
  369. void printmpint(const char *label, mp_int *mp) {
  370. buffer *buf = buf_new(1000);
  371. buf_putmpint(buf, mp);
  372. fprintf(stderr, "%d bits ", mp_count_bits(mp));
  373. printhex(label, buf->data, buf->len);
  374. buf_free(buf);
  375. }
  376. #endif
  377. /* Strip all control characters from text (a null-terminated string), except
  378. * for '\n', '\r' and '\t'.
  379. * The result returned is a newly allocated string, this must be free()d after
  380. * use */
  381. char * stripcontrol(const char * text) {
  382. char * ret;
  383. int len, pos;
  384. int i;
  385. len = strlen(text);
  386. ret = m_malloc(len+1);
  387. pos = 0;
  388. for (i = 0; i < len; i++) {
  389. if ((text[i] <= '~' && text[i] >= ' ') /* normal printable range */
  390. || text[i] == '\n' || text[i] == '\r' || text[i] == '\t') {
  391. ret[pos] = text[i];
  392. pos++;
  393. }
  394. }
  395. ret[pos] = 0x0;
  396. return ret;
  397. }
  398. /* reads the contents of filename into the buffer buf, from the current
  399. * position, either to the end of the file, or the buffer being full.
  400. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  401. int buf_readfile(buffer* buf, const char* filename) {
  402. int fd = -1;
  403. int len;
  404. int maxlen;
  405. int ret = DROPBEAR_FAILURE;
  406. fd = open(filename, O_RDONLY);
  407. if (fd < 0) {
  408. goto out;
  409. }
  410. do {
  411. maxlen = buf->size - buf->pos;
  412. len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
  413. if (len < 0) {
  414. if (errno == EINTR || errno == EAGAIN) {
  415. continue;
  416. }
  417. goto out;
  418. }
  419. buf_incrwritepos(buf, len);
  420. } while (len < maxlen && len > 0);
  421. ret = DROPBEAR_SUCCESS;
  422. out:
  423. if (fd >= 0) {
  424. m_close(fd);
  425. }
  426. return ret;
  427. }
  428. /* get a line from the file into buffer in the style expected for an
  429. * authkeys file.
  430. * Will return DROPBEAR_SUCCESS if data is read, or DROPBEAR_FAILURE on EOF.*/
  431. /* Only used for ~/.ssh/known_hosts and ~/.ssh/authorized_keys */
  432. #if DROPBEAR_CLIENT || DROPBEAR_SVR_PUBKEY_AUTH
  433. int buf_getline(buffer * line, FILE * authfile) {
  434. int c = EOF;
  435. buf_setpos(line, 0);
  436. buf_setlen(line, 0);
  437. while (line->pos < line->size) {
  438. c = fgetc(authfile); /*getc() is weird with some uClibc systems*/
  439. if (c == EOF || c == '\n' || c == '\r') {
  440. goto out;
  441. }
  442. buf_putbyte(line, (unsigned char)c);
  443. }
  444. TRACE(("leave getauthline: line too long"))
  445. /* We return success, but the line length will be zeroed - ie we just
  446. * ignore that line */
  447. buf_setlen(line, 0);
  448. out:
  449. /* if we didn't read anything before EOF or error, exit */
  450. if (c == EOF && line->pos == 0) {
  451. return DROPBEAR_FAILURE;
  452. } else {
  453. buf_setpos(line, 0);
  454. return DROPBEAR_SUCCESS;
  455. }
  456. }
  457. #endif
  458. /* make sure that the socket closes */
  459. void m_close(int fd) {
  460. int val;
  461. if (fd < 0) {
  462. return;
  463. }
  464. do {
  465. val = close(fd);
  466. } while (val < 0 && errno == EINTR);
  467. if (val < 0 && errno != EBADF) {
  468. /* Linux says EIO can happen */
  469. dropbear_exit("Error closing fd %d, %s", fd, strerror(errno));
  470. }
  471. }
  472. void setnonblocking(int fd) {
  473. TRACE(("setnonblocking: %d", fd))
  474. #if DROPBEAR_FUZZ
  475. if (fuzz.fuzzing) {
  476. return;
  477. }
  478. #endif
  479. if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
  480. if (errno == ENODEV) {
  481. /* Some devices (like /dev/null redirected in)
  482. * can't be set to non-blocking */
  483. TRACE(("ignoring ENODEV for setnonblocking"))
  484. } else {
  485. {
  486. dropbear_exit("Couldn't set nonblocking");
  487. }
  488. }
  489. }
  490. TRACE(("leave setnonblocking"))
  491. }
  492. void disallow_core() {
  493. struct rlimit lim = {0};
  494. if (getrlimit(RLIMIT_CORE, &lim) < 0) {
  495. TRACE(("getrlimit(RLIMIT_CORE) failed"));
  496. }
  497. lim.rlim_cur = 0;
  498. if (setrlimit(RLIMIT_CORE, &lim) < 0) {
  499. TRACE(("setrlimit(RLIMIT_CORE) failed"));
  500. }
  501. }
  502. /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE, with the result in *val */
  503. int m_str_to_uint(const char* str, unsigned int *val) {
  504. unsigned long l;
  505. char *endp;
  506. l = strtoul(str, &endp, 10);
  507. if (endp == str || *endp != '\0') {
  508. /* parse error */
  509. return DROPBEAR_FAILURE;
  510. }
  511. /* The c99 spec doesn't actually seem to define EINVAL, but most platforms
  512. * I've looked at mention it in their manpage */
  513. if ((l == 0 && errno == EINVAL)
  514. || (l == ULONG_MAX && errno == ERANGE)
  515. || (l > UINT_MAX)) {
  516. return DROPBEAR_FAILURE;
  517. } else {
  518. *val = l;
  519. return DROPBEAR_SUCCESS;
  520. }
  521. }
  522. /* Returns malloced path. inpath beginning with '~/' expanded,
  523. otherwise returned as-is */
  524. char * expand_homedir_path(const char *inpath) {
  525. struct passwd *pw = NULL;
  526. if (strncmp(inpath, "~/", 2) == 0) {
  527. char *homedir = getenv("HOME");
  528. if (!homedir) {
  529. pw = getpwuid(getuid());
  530. if (pw) {
  531. homedir = pw->pw_dir;
  532. }
  533. }
  534. if (homedir) {
  535. int len = strlen(inpath)-2 + strlen(homedir) + 2;
  536. char *buf = m_malloc(len);
  537. snprintf(buf, len, "%s/%s", homedir, inpath+2);
  538. return buf;
  539. }
  540. }
  541. /* Fallback */
  542. return m_strdup(inpath);
  543. }
  544. int constant_time_memcmp(const void* a, const void *b, size_t n)
  545. {
  546. const char *xa = a, *xb = b;
  547. uint8_t c = 0;
  548. size_t i;
  549. for (i = 0; i < n; i++)
  550. {
  551. c |= (xa[i] ^ xb[i]);
  552. }
  553. return c;
  554. }
  555. /* higher-resolution monotonic timestamp, falls back to gettimeofday */
  556. void gettime_wrapper(struct timespec *now) {
  557. struct timeval tv;
  558. #if DROPBEAR_FUZZ
  559. if (fuzz.fuzzing) {
  560. /* time stands still when fuzzing */
  561. now->tv_sec = 5;
  562. now->tv_nsec = 0;
  563. }
  564. #endif
  565. #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
  566. /* POSIX monotonic clock. Newer Linux, BSD, MacOSX >10.12 */
  567. if (clock_gettime(CLOCK_MONOTONIC, now) == 0) {
  568. return;
  569. }
  570. #endif
  571. #if defined(__linux__) && defined(SYS_clock_gettime)
  572. {
  573. /* Old linux toolchain - kernel might support it but not the build headers */
  574. /* Also glibc <2.17 requires -lrt which we neglect to add */
  575. static int linux_monotonic_failed = 0;
  576. if (!linux_monotonic_failed) {
  577. /* CLOCK_MONOTONIC isn't in some headers */
  578. int clock_source_monotonic = 1;
  579. if (syscall(SYS_clock_gettime, clock_source_monotonic, now) == 0) {
  580. return;
  581. } else {
  582. /* Don't try again */
  583. linux_monotonic_failed = 1;
  584. }
  585. }
  586. }
  587. #endif /* linux fallback clock_gettime */
  588. #if defined(HAVE_MACH_ABSOLUTE_TIME)
  589. {
  590. /* OS X pre 10.12, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
  591. static mach_timebase_info_data_t timebase_info;
  592. uint64_t scaled_time;
  593. if (timebase_info.denom == 0) {
  594. mach_timebase_info(&timebase_info);
  595. }
  596. scaled_time = mach_absolute_time() * timebase_info.numer / timebase_info.denom;
  597. now->tv_sec = scaled_time / 1000000000;
  598. now->tv_nsec = scaled_time % 1000000000;
  599. }
  600. #endif /* osx mach_absolute_time */
  601. /* Fallback for everything else - this will sometimes go backwards */
  602. gettimeofday(&tv, NULL);
  603. now->tv_sec = tv.tv_sec;
  604. now->tv_nsec = 1000*tv.tv_usec;
  605. }
  606. /* second-resolution monotonic timestamp */
  607. time_t monotonic_now() {
  608. struct timespec ts;
  609. gettime_wrapper(&ts);
  610. return ts.tv_sec;
  611. }
  612. void fsync_parent_dir(const char* fn) {
  613. #ifdef HAVE_LIBGEN_H
  614. char *fn_dir = m_strdup(fn);
  615. char *dir = dirname(fn_dir);
  616. int dirfd = open(dir, O_RDONLY);
  617. if (dirfd != -1) {
  618. if (fsync(dirfd) != 0) {
  619. TRACE(("fsync of directory %s failed: %s", dir, strerror(errno)))
  620. }
  621. m_close(dirfd);
  622. } else {
  623. TRACE(("error opening directory %s for fsync: %s", dir, strerror(errno)))
  624. }
  625. m_free(fn_dir);
  626. #endif
  627. }
  628. int fd_read_pending(int fd) {
  629. fd_set fds;
  630. struct timeval timeout;
  631. DROPBEAR_FD_ZERO(&fds);
  632. FD_SET(fd, &fds);
  633. while (1) {
  634. timeout.tv_sec = 0;
  635. timeout.tv_usec = 0;
  636. if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
  637. if (errno == EINTR) {
  638. continue;
  639. }
  640. return 0;
  641. }
  642. return FD_ISSET(fd, &fds);
  643. }
  644. }
  645. int m_snprintf(char *str, size_t size, const char *format, ...) {
  646. va_list param;
  647. int ret;
  648. va_start(param, format);
  649. ret = vsnprintf(str, size, format, param);
  650. va_end(param);
  651. if (ret < 0) {
  652. dropbear_exit("snprintf failed");
  653. }
  654. return ret;
  655. }