Bug Summary

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