]> granicus.if.org Git - sudo/blob - plugins/sudoers/timeout.c
Add SPDX-License-Identifier to files.
[sudo] / plugins / sudoers / timeout.c
1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 /*
20  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
21  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
22  */
23
24 #include <config.h>
25
26 #include <sys/types.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stddef.h>
30 #ifdef HAVE_STRING_H
31 # include <string.h>
32 #endif /* HAVE_STRING_H */
33 #ifdef HAVE_STRINGS_H
34 # include <strings.h>
35 #endif /* HAVE_STRINGS_H */
36 #include <ctype.h>
37 #include <errno.h>
38 #include <limits.h>
39
40 #include "sudo_compat.h"
41 #include "sudoers_debug.h"
42 #include "parse.h"
43
44 /*
45  * Parse a command timeout in sudoers in the format 1d2h3m4s
46  * (days, hours, minutes, seconds) or a number of seconds with no suffix.
47  * Returns the number of seconds or -1 on error.
48  */
49 int
50 parse_timeout(const char *timestr)
51 {
52     debug_decl(parse_timeout, SUDOERS_DEBUG_PARSER)
53     const char suffixes[] = "dhms";
54     const char *cp = timestr;
55     int timeout = 0;
56     int idx = 0;
57
58     do {
59         char *ep;
60         char ch;
61         long l;
62
63         /* Parse number, must be present and positive. */
64         errno = 0;
65         l = strtol(cp, &ep, 10);
66         if (ep == cp) {
67             /* missing timeout */
68             errno = EINVAL;
69             debug_return_int(-1);
70         }
71         if (errno == ERANGE || l < 0 || l > INT_MAX)
72             goto overflow;
73
74         /* Find a matching suffix or return an error. */
75         if (*ep != '\0') {
76             ch = tolower((unsigned char)*ep++);
77             while (suffixes[idx] != ch) {
78                 if (suffixes[idx] == '\0') {
79                     /* parse error */
80                     errno = EINVAL;
81                     debug_return_int(-1);
82                 }
83                 idx++;
84             }
85
86             /* Apply suffix. */
87             switch (ch) {
88             case 'd':
89                 if (l > INT_MAX / (24 * 60 * 60))
90                     goto overflow;
91                 l *= 24 * 60 * 60;
92                 break;
93             case 'h':
94                 if (l > INT_MAX / (60 * 60))
95                     goto overflow;
96                 l *= 60 * 60;
97                 break;
98             case 'm':
99                 if (l > INT_MAX / 60)
100                     goto overflow;
101                 l *= 60;
102                 break;
103             }
104             if (l > INT_MAX - timeout)
105                 goto overflow;
106         }
107         cp = ep;
108
109         timeout += l;
110     } while (*cp != '\0');
111
112     debug_return_int(timeout);
113 overflow:
114     errno = ERANGE;
115     debug_return_int(-1);
116 }