Bug Summary

File:src/libexec/login_lchpass/../../usr.bin/passwd/pwd_check.c
Warning:line 117, column 3
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pwd_check.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/libexec/login_lchpass/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused -fdebug-compilation-dir=/usr/src/libexec/login_lchpass/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/libexec/login_lchpass/../../usr.bin/passwd/pwd_check.c
1/* $OpenBSD: pwd_check.c,v 1.18 2023/05/08 16:11:41 tobias Exp $ */
2
3/*
4 * Copyright 2000 Niels Provos <provos@citi.umich.edu>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Niels Provos.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34#include <sys/wait.h>
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <limits.h>
41#include <errno(*__errno()).h>
42#include <err.h>
43#include <regex.h>
44#include <grp.h>
45#include <paths.h>
46#include <login_cap.h>
47#include <signal.h>
48
49int pwd_check(login_cap_t *, char *);
50int pwd_gettries(login_cap_t *);
51
52struct pattern {
53 char *match;
54 int flags;
55 char *response;
56};
57
58struct pattern patterns[] = {
59 {
60 "^[0-9]*$",
61 REG_EXTENDED0001|REG_NOSUB0004,
62 "Please don't use all-digit passwords."
63 },
64 {
65 "^[a-z]{1,9}$",
66 REG_EXTENDED0001|REG_NOSUB0004,
67 "Please don't use an all-lower case password."
68 },
69 {
70 "^[a-z]{1,6}[0-9]+$",
71 REG_EXTENDED0001|REG_NOSUB0004|REG_ICASE0002,
72 "Please use a more complicated password."
73 },
74 {
75 "^([a-z][0-9]){1,4}$",
76 REG_EXTENDED0001|REG_NOSUB0004|REG_ICASE0002,
77 "Please use a more complicated password."
78 },
79 {
80 "^([0-9][a-z]){1,4}$",
81 REG_EXTENDED0001|REG_NOSUB0004|REG_ICASE0002,
82 "Please use a more complicated password."
83 }
84};
85
86int
87pwd_check(login_cap_t *lc, char *password)
88{
89 regex_t rgx;
90 int i, res, min_len;
91 char *checker;
92 char *argp[] = { "sh", "-c", NULL((void *)0), NULL((void *)0)};
93 int pipefds[2];
94 pid_t child;
95 uid_t uid;
96 gid_t gid;
97
98 min_len = (int)login_getcapnum(lc, "minpasswordlen", 6, 6);
99 if (min_len > 0 && strlen(password) < min_len) {
1
Assuming 'min_len' is <= 0
100 fprintf(stderr(&__sF[2]), "Please enter a longer password.\n");
101 return (0);
102 }
103
104 /* External password check program */
105 checker = login_getcapstr(lc, "passwordcheck", NULL((void *)0), NULL((void *)0));
106
107 /* Pipes are only used for external checker */
108 if (checker != NULL((void *)0) && pipe(pipefds) == -1) {
2
Assuming 'checker' is equal to NULL
109 warn("pipe");
110 goto out;
111 }
112
113 /* Check password in low-privileged child */
114 switch (child = fork()) {
3
Control jumps to 'case -1:' at line 115
115 case -1:
116 warn("fork");
117 close(pipefds[0]);
4
1st function call argument is an uninitialized value
118 close(pipefds[1]);
119 goto out;
120 case 0:
121 (void)signal(SIGINT2, SIG_DFL(void (*)(int))0);
122 (void)signal(SIGQUIT3, SIG_DFL(void (*)(int))0);
123 uid = getuid();
124 gid = getgid();
125 if (setresgid(gid, gid, gid) == -1) {
126 warn("setresgid");
127 exit(1);
128 }
129 if (setgroups(1, &gid) == -1) {
130 warn("setgroups");
131 exit(1);
132 }
133 if (setresuid(uid, uid, uid) == -1) {
134 warn("setresuid");
135 exit(1);
136 }
137
138 if (checker == NULL((void *)0)) {
139 if (pledge("stdio", NULL((void *)0)) == -1)
140 err(1, "pledge");
141
142 for (i = 0; i < sizeof(patterns) / sizeof(*patterns); i++) {
143 int ret;
144
145 if (regcomp(&rgx, patterns[i].match,
146 patterns[i].flags) != 0)
147 continue;
148 ret = regexec(&rgx, password, 0, NULL((void *)0), 0);
149 regfree(&rgx);
150 if (ret == 0) {
151 fprintf(stderr(&__sF[2]), "%s\n", patterns[i].response);
152 exit(1);
153 }
154 }
155 /* no external checker in use, accept the password */
156 exit(0);
157 }
158
159 if (pledge("stdio exec", NULL((void *)0)) == -1)
160 err(1, "pledge");
161
162 /* Otherwise, pass control to checker program */
163 argp[2] = checker;
164 if (dup2(pipefds[0], STDIN_FILENO0) == -1) {
165 warn("dup2");
166 exit(1);
167 }
168 close(pipefds[0]);
169 close(pipefds[1]);
170
171 if (execv(_PATH_BSHELL"/bin/sh", argp) == -1) {
172 warn("exec");
173 exit(1);
174 }
175 /* NOTREACHED */
176 default:
177 break; /* parent continues below */
178 }
179
180 if (checker != NULL((void *)0)) {
181 /* Send the password to STDIN of child */
182 close(pipefds[0]);
183 write(pipefds[1], password, strlen(password) + 1);
184 close(pipefds[1]);
185 }
186
187 /* get the return value from the child */
188 while (waitpid(child, &res, 0) == -1) {
189 if (errno(*__errno()) != EINTR4) {
190 warn("waitpid");
191 goto out;
192 }
193 }
194 if (WIFEXITED(res)(((res) & 0177) == 0) && WEXITSTATUS(res)(int)(((unsigned)(res) >> 8) & 0xff) == 0) {
195 free(checker);
196 return (1);
197 }
198
199 out:
200 free(checker);
201 fprintf(stderr(&__sF[2]), "Please use a different password. Unusual capitalization,\n");
202 fprintf(stderr(&__sF[2]), "control characters, or digits are suggested.\n");
203
204 return (0);
205}
206
207int
208pwd_gettries(login_cap_t *lc)
209{
210 quad_t ntries;
211
212 if ((ntries = login_getcapnum(lc, "passwordtries", -1, -1)) != -1) {
213 if (ntries >= 0 && ntries <= INT_MAX0x7fffffff)
214 return((int)ntries);
215 fprintf(stderr(&__sF[2]),
216 "Warning: pwdtries out of range in /etc/login.conf");
217 }
218
219 /*
220 * If no amount of tries is specified, return a default of 3,
221 * meaning that after 3 attempts where the user is foiled by the
222 * password checks, it will no longer be checked and they can set
223 * it to whatever they like. This is the historic BSD behavior.
224 */
225 return (3);
226}