Bug Summary

File:obj-scan-build/libshouldbeinlibc/../../libshouldbeinlibc/ugids-verify-auth.c
Location:line 189, column 10
Description:Memory is never released; potential leak of memory pointed to by 'svma_state.auths'

Annotated Source Code

1/* Verify user/group passwords and authenticate accordingly
2
3 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
4 Written by Miles Bader <miles@gnu.ai.mit.edu>
5 This file is part of the GNU Hurd.
6
7 The GNU Hurd is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 The GNU Hurd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
20
21#include <stdlib.h>
22#include <string.h>
23#include <hurd.h>
24#include <ctype.h>
25#include <unistd.h>
26#include <argp.h>
27#include <pwd.h>
28#include <grp.h>
29
30#include <hurd/paths.h>
31#include <hurd/password.h>
32
33#include "ugids.h"
34
35/* Accumulated information from authentication various passwords. */
36struct svma_state
37{
38 /* The password server. */
39 file_t server;
40
41 /* An auth port for each password that was verify by the server. */
42 auth_t *auths;
43 size_t num_auths;
44};
45
46/* Append the auth ports in AUTHS, of length NUM_AUTHS, to the auth port
47 vector in SS, returning 0 if successful, or an error. */
48static error_t
49svma_state_add_auths (struct svma_state *ss,
50 const auth_t *auths, size_t num_auths)
51{
52 auth_t *new = realloc (ss->auths,
8
Memory is allocated
53 (ss->num_auths + num_auths) * sizeof (auth_t));
54 if (new)
9
Assuming 'new' is non-null
10
Taking true branch
55 {
56 ss->auths = new;
57 while (num_auths--)
11
Loop condition is true. Entering loop body
12
Loop condition is false. Execution continues on line 59
58 ss->auths[ss->num_auths++] = *auths++;
59 return 0;
60 }
61 else
62 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
63}
64
65/* Get authentication from PASSWORD using the hurd password server. */
66static error_t
67server_verify_make_auth (const char *password,
68 uid_t id, int is_group,
69 void *pwd_or_grp, void *hook)
70{
71 auth_t auth;
72 struct svma_state *svma_state = hook;
73 error_t (*check) (io_t server, uid_t id, const char *passwd, auth_t *auth) =
74 is_group ? password_check_group : password_check_user;
75 error_t err = (*check) (svma_state->server, id, password, &auth);
76
77 if (! err)
78 /* PASSWORD checked out ok; the corresponding authentication is in AUTH. */
79 {
80 err = svma_state_add_auths (svma_state, &auth, 1);
81 if (err)
82 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), auth);
83 }
84
85 return err;
86}
87
88/* Verify that we have the right to the ids in UGIDS, given that we already
89 possess those in HAVE_UIDS and HAVE_GIDS (asking for passwords where
90 necessary), and return corresponding authentication in AUTH; the auth
91 ports in FROM, of length NUM_FROM, are used to supplement the auth port of
92 the current process if necessary. 0 is returned if access should be
93 allowed, otherwise EINVAL if an incorrect password was entered, or an
94 error relating to resource failure. GETPASS_FN and GETPASS_HOOK are as
95 for the idvec_verify function in <idvec.h>. */
96error_t
97ugids_verify_make_auth (const struct ugids *ugids,
98 const struct idvec *have_uids,
99 const struct idvec *have_gids,
100 char *(*getpass_fn) (const char *prompt,
101 uid_t id, int is_group,
102 void *pwd_or_grp, void *hook),
103 void *getpass_hook,
104 const auth_t *from, size_t num_from,
105 auth_t *auth)
106{
107 error_t err;
108 /* By default, get authentication from the password server. */
109 struct svma_state svma_state;
110 error_t (*verify_fn) (const char *password,
111 uid_t id, int is_group,
112 void *pwd_or_grp, void *hook)
113 = server_verify_make_auth;
114 void *verify_hook = &svma_state;
115
116 /* Try to open the hurd password server. */
117 svma_state.server = file_name_lookup (_SERVERS_PASSWORD"/servers/" "password", 0, 0);
118
119 if (svma_state.server == MACH_PORT_NULL((mach_port_t) 0))
1
Taking false branch
120 /* Can't open the password server, try to use our own authority in
121 the traditional unix manner. */
122 {
123 verify_fn = 0;
124 verify_hook = 0;
125 }
126 else
127 {
128 /* Must initialize list to empty so svma_state_add_auths works. */
129 svma_state.auths = NULL((void*)0);
130 svma_state.num_auths = 0;
131 }
132
133 /* Check passwords. */
134 err = ugids_verify (ugids, have_uids, have_gids,
135 getpass_fn, getpass_hook, verify_fn, verify_hook);
136
137 if (! err)
2
Assuming 'err' is 0
3
Taking true branch
138 {
139 /* The user apparently has access to all the ids, try to grant the
140 corresponding authentication. */
141 if (verify_fn)
4
Taking true branch
142 /* Merge the authentication we got from the password server into our
143 result. */
144 {
145 if (num_from > 0)
5
Assuming 'num_from' is > 0
6
Taking true branch
146 /* Use FROM as well as the passwords to get authentication. */
147 err = svma_state_add_auths (&svma_state, from, num_from);
7
Calling 'svma_state_add_auths'
13
Returned allocated memory
148
149 if (! err)
14
Taking true branch
150 {
151 auth_t cur_auth = getauth ();
152
153 err =
154 auth_makeauth (cur_auth,
155 svma_state.auths, MACH_MSG_TYPE_COPY_SEND19,
156 svma_state.num_auths,
157 ugids->eff_uids.ids, ugids->eff_uids.num,
158 ugids->avail_uids.ids, ugids->avail_uids.num,
159 ugids->eff_gids.ids, ugids->eff_gids.num,
160 ugids->avail_gids.ids, ugids->avail_gids.num,
161 auth);
162 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), cur_auth);
163
164 /* Avoid deallocating FROM when we clean up SVMA_STATE. */
165 svma_state.num_auths -= num_from;
166 }
167 }
168 else
169 /* Try to authenticate the old fashioned way... */
170 err = ugids_make_auth (ugids, from, num_from, auth);
171 }
172
173 if (verify_fn)
15
Taking true branch
174 /* Clean up any left over state. */
175 {
176 unsigned int i;
177
178 /* Get rid of auth ports. */
179 for (i = 0; i < svma_state.num_auths; i++)
16
Loop condition is false. Execution continues on line 183
180 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), svma_state.auths[i]);
181
182 /* Close password server. */
183 mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), svma_state.server);
184
185 if (svma_state.num_auths > 0)
17
Taking false branch
186 free (svma_state.auths);
187 }
188
189 return err;
18
Memory is never released; potential leak of memory pointed to by 'svma_state.auths'
190}