1 /*****************************************************************************
2 * Written by Chris Dunlap <cdunlap@llnl.gov>.
3 * Copyright (C) 2007-2020 Lawrence Livermore National Security, LLC.
4 * Copyright (C) 2002-2007 The Regents of the University of California.
5 * UCRL-CODE-155910.
6 *
7 * This file is part of the MUNGE Uid 'N' Gid Emporium (MUNGE).
8 * For details, see <https://dun.github.io/munge/>.
9 *
10 * MUNGE is free software: you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free
12 * Software Foundation, either version 3 of the License, or (at your option)
13 * any later version. Additionally for the MUNGE library (libmunge), you
14 * can redistribute it and/or modify it under the terms of the GNU Lesser
15 * General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * MUNGE is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * and GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * and GNU Lesser General Public License along with MUNGE. If not, see
25 * <http://www.gnu.org/licenses/>.
26 *****************************************************************************/
27
28
29 #if HAVE_CONFIG_H
30 # include "config.h"
31 #endif /* HAVE_CONFIG_H */
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <limits.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <munge.h>
40 #include "log.h"
41 #include "munge_defs.h"
42
43
44 #define INITIAL_BUFFER_SIZE 4096
45 #define MAXIMUM_BUFFER_SIZE MUNGE_MAXIMUM_REQ_LEN
46 /*
47 * MUNGE_MAXIMUM_REQ_LEN (in munge_defs.h) specifies the maximum size of a
48 * request message transmitted over the unix domain socket. Since messages
49 * greater than this length will be rejected, MAXIMUM_BUFFER_SIZE is used to
50 * limit the size of the memory allocation for bufmem.
51 */
52
53
54 void
read_data_from_file(FILE * fp,void ** buf,int * len)55 read_data_from_file (FILE *fp, void **buf, int *len)
56 {
57 unsigned char *bufmem; /* base ptr to buffer memory */
58 unsigned char *bufptr; /* current ptr to unused bufmem */
59 unsigned char *buftmp; /* tmp ptr to bufmem for realloc() */
60 size_t bufsiz; /* size allocated for bufmem */
61 size_t buflen; /* num bytes of unused bufmem */
62 size_t bufuse; /* num bytes of used bufmem */
63 size_t n;
64
65 assert (fp != NULL);
66 assert (buf != NULL);
67 assert (len != NULL);
68
69 bufsiz = INITIAL_BUFFER_SIZE;
70 bufmem = bufptr = malloc (bufsiz);
71 if (bufmem == NULL) {
72 log_errno (EMUNGE_NO_MEMORY, LOG_ERR,
73 "Failed to allocate %lu bytes", bufsiz);
74 }
75 buflen = bufsiz;
76
77 /* Since this reads from a standard I/O stream, there is no guarantee that
78 * the stream provides random access (e.g., when reading from a pipe).
79 * As such, it cannot rely on seeking to the end of the stream to
80 * determine the file length before seeking back to the beginning to
81 * start reading. Consequently, this routine realloc()s the buffer to
82 * grow it as needed while reading from the fp steam.
83 */
84 for (;;) {
85 n = fread (bufptr, 1, buflen, fp);
86 bufptr += n;
87 buflen -= n;
88 if (buflen > 0) {
89 if (feof (fp)) {
90 break;
91 }
92 else if (ferror (fp)) {
93 log_err (EMUNGE_SNAFU, LOG_ERR,
94 "Failed to read from file");
95 }
96 else {
97 log_err (EMUNGE_SNAFU, LOG_ERR,
98 "Failed to read from file: Unexpected short count");
99 }
100 }
101 assert (buflen == 0);
102 assert (bufsiz == bufptr - bufmem);
103 bufuse = bufsiz;
104 bufsiz *= 2;
105 if (bufsiz > MAXIMUM_BUFFER_SIZE) {
106 free (bufmem);
107 log_errno (EMUNGE_SNAFU, LOG_ERR,
108 "Exceeded maximum memory allocation");
109 }
110 buftmp = realloc (bufmem, bufsiz);
111 if (buftmp == NULL) {
112 free (bufmem);
113 log_errno (EMUNGE_NO_MEMORY, LOG_ERR,
114 "Failed to allocate %lu bytes", bufsiz);
115 }
116 buflen = bufsiz - bufuse;
117 bufptr = buftmp + bufuse;
118 bufmem = buftmp;
119 }
120 n = bufptr - bufmem;
121 if (n == 0) {
122 free (bufmem);
123 *buf = NULL;
124 *len = 0;
125 return;
126 }
127 /* If the fp has exactly 'len' bytes remaining, fread (ptr, 1, len, fp)
128 * will return a value equal to 'len'. But the EOF will not be detected
129 * until the next fread() which will return a value of 0. Consequently,
130 * realloc() will double the buffer before this final iteration of the
131 * loop thereby guaranteeing (buflen > 0). The if-guard here is just
132 * for safety/paranoia.
133 */
134 assert (buflen > 0);
135 if (buflen > 0) {
136 bufmem[n] = '\0';
137 }
138 if (n > INT_MAX) {
139 log_err (EMUNGE_SNAFU, LOG_ERR, "Exceeded maximum file size");
140 }
141 *buf = bufmem;
142 *len = (int) n;
143 return;
144 }
145
146
147 void
read_data_from_string(const char * s,void ** buf,int * len)148 read_data_from_string (const char *s, void **buf, int *len)
149 {
150 size_t n;
151 char *p;
152
153 assert (buf != NULL);
154 assert (len != NULL);
155
156 *buf = NULL;
157 *len = 0;
158
159 if (s == NULL) {
160 return;
161 }
162 n = strlen (s);
163 if (n == 0) {
164 return;
165 }
166 p = malloc (n + 1);
167 if (p == NULL) {
168 log_errno (EMUNGE_NO_MEMORY, LOG_ERR,
169 "Failed to allocate %lu bytes", n + 1);
170 }
171 strncpy (p, s, n + 1);
172 p[n] = '\0'; /* null termination here is technically unnecessary */
173
174 if (n > INT_MAX) {
175 log_err (EMUNGE_SNAFU, LOG_ERR, "Exceeded maximum string size");
176 }
177 *buf = p;
178 *len = (int) n;
179 return;
180 }
181