/src/openssh/openbsd-compat/mktemp.c
Line | Count | Source |
1 | | /* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ |
2 | | /* Changes: Removed mktemp */ |
3 | | |
4 | | /* $OpenBSD: mktemp.c,v 1.30 2010/03/21 23:09:30 schwarze Exp $ */ |
5 | | /* |
6 | | * Copyright (c) 1996-1998, 2008 Theo de Raadt |
7 | | * Copyright (c) 1997, 2008-2009 Todd C. Miller |
8 | | * |
9 | | * Permission to use, copy, modify, and distribute this software for any |
10 | | * purpose with or without fee is hereby granted, provided that the above |
11 | | * copyright notice and this permission notice appear in all copies. |
12 | | * |
13 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
14 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
15 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
16 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
17 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
18 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
19 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
20 | | */ |
21 | | |
22 | | /* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */ |
23 | | |
24 | | #include "includes.h" |
25 | | |
26 | | #include <sys/types.h> |
27 | | #include <sys/stat.h> |
28 | | #include <errno.h> |
29 | | #include <fcntl.h> |
30 | | #include <limits.h> |
31 | | #include <stdio.h> |
32 | | #include <stdlib.h> |
33 | | #include <string.h> |
34 | | #include <ctype.h> |
35 | | #include <unistd.h> |
36 | | |
37 | | #ifdef mkstemp |
38 | | #undef mkstemp |
39 | | #endif |
40 | | int mkstemp(char *); |
41 | | |
42 | | /* |
43 | | * From glibc man page: 'In glibc versions 2.06 and earlier, the file is |
44 | | * created with permissions 0666, that is, read and write for all users.' |
45 | | * Provide a wrapper to make sure the mask is reasonable (POSIX requires |
46 | | * mode 0600, so mask off any other bits). |
47 | | */ |
48 | | int |
49 | | _ssh_mkstemp(char *template) |
50 | 249 | { |
51 | 249 | mode_t mask; |
52 | 249 | int ret; |
53 | | |
54 | 249 | mask = umask(0177); |
55 | 249 | ret = mkstemp(template); |
56 | 249 | (void)umask(mask); |
57 | 249 | return ret; |
58 | 249 | } |
59 | | |
60 | | #if !defined(HAVE_MKDTEMP) |
61 | | |
62 | | #define MKTEMP_NAME 0 |
63 | | #define MKTEMP_FILE 1 |
64 | | #define MKTEMP_DIR 2 |
65 | | |
66 | | #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" |
67 | | #define NUM_CHARS (sizeof(TEMPCHARS) - 1) |
68 | | |
69 | | static int |
70 | | mktemp_internal(char *path, int slen, int mode) |
71 | | { |
72 | | char *start, *cp, *ep; |
73 | | const char *tempchars = TEMPCHARS; |
74 | | unsigned int r, tries; |
75 | | struct stat sb; |
76 | | size_t len; |
77 | | int fd; |
78 | | |
79 | | len = strlen(path); |
80 | | if (len == 0 || slen < 0 || (size_t)slen >= len) { |
81 | | errno = EINVAL; |
82 | | return(-1); |
83 | | } |
84 | | ep = path + len - slen; |
85 | | |
86 | | tries = 1; |
87 | | for (start = ep; start > path && start[-1] == 'X'; start--) { |
88 | | if (tries < INT_MAX / NUM_CHARS) |
89 | | tries *= NUM_CHARS; |
90 | | } |
91 | | tries *= 2; |
92 | | |
93 | | do { |
94 | | for (cp = start; cp != ep; cp++) { |
95 | | r = arc4random_uniform(NUM_CHARS); |
96 | | *cp = tempchars[r]; |
97 | | } |
98 | | |
99 | | switch (mode) { |
100 | | case MKTEMP_NAME: |
101 | | if (lstat(path, &sb) != 0) |
102 | | return(errno == ENOENT ? 0 : -1); |
103 | | break; |
104 | | case MKTEMP_FILE: |
105 | | fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); |
106 | | if (fd != -1 || errno != EEXIST) |
107 | | return(fd); |
108 | | break; |
109 | | case MKTEMP_DIR: |
110 | | if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0) |
111 | | return(0); |
112 | | if (errno != EEXIST) |
113 | | return(-1); |
114 | | break; |
115 | | } |
116 | | } while (--tries); |
117 | | |
118 | | errno = EEXIST; |
119 | | return(-1); |
120 | | } |
121 | | |
122 | | #if 0 |
123 | | char *_mktemp(char *); |
124 | | |
125 | | char * |
126 | | _mktemp(char *path) |
127 | | { |
128 | | if (mktemp_internal(path, 0, MKTEMP_NAME) == -1) |
129 | | return(NULL); |
130 | | return(path); |
131 | | } |
132 | | |
133 | | __warn_references(mktemp, |
134 | | "warning: mktemp() possibly used unsafely; consider using mkstemp()"); |
135 | | |
136 | | char * |
137 | | mktemp(char *path) |
138 | | { |
139 | | return(_mktemp(path)); |
140 | | } |
141 | | #endif |
142 | | |
143 | | int |
144 | | mkstemp(char *path) |
145 | | { |
146 | | return(mktemp_internal(path, 0, MKTEMP_FILE)); |
147 | | } |
148 | | |
149 | | int |
150 | | mkstemps(char *path, int slen) |
151 | | { |
152 | | return(mktemp_internal(path, slen, MKTEMP_FILE)); |
153 | | } |
154 | | |
155 | | char * |
156 | | mkdtemp(char *path) |
157 | | { |
158 | | int error; |
159 | | |
160 | | error = mktemp_internal(path, 0, MKTEMP_DIR); |
161 | | return(error ? NULL : path); |
162 | | } |
163 | | |
164 | | #endif /* !defined(HAVE_MKDTEMP) */ |