View | Details | Raw Unified | Return to bug 125 | Differences between
and this patch

Collapse All | Expand All

(-)LICENCE (+1 lines)
Lines 203-208 OpenSSH contains no GPL code. Link Here
203
	Wayne Schroeder
203
	Wayne Schroeder
204
	William Jones
204
	William Jones
205
	Darren Tucker
205
	Darren Tucker
206
	Sun Microsystems
206
207
207
     * Redistribution and use in source and binary forms, with or without
208
     * Redistribution and use in source and binary forms, with or without
208
     * modification, are permitted provided that the following conditions
209
     * modification, are permitted provided that the following conditions
(-)Makefile.in (-1 / +2 lines)
Lines 85-91 SSHDOBJS=sshd.o auth-rhosts.o auth-passw Link Here
85
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
85
	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
86
	auth-krb5.o \
86
	auth-krb5.o \
87
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
87
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
88
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o audit.o
88
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
89
	audit.o audit-bsm.o
89
90
90
MANPAGES	= scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
91
MANPAGES	= scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
91
MANPAGES_IN	= scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
92
MANPAGES_IN	= scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
(-)README.platform (-3 / +15 lines)
Lines 23-30 openssl-devel, zlib, minres, minires-dev Link Here
23
23
24
Solaris
24
Solaris
25
-------
25
-------
26
Currently, sshd does not support BSM auditting.  This can show up as errors
26
If you enable BSM auditing on Solaris, you need to update audit_event(4)
27
when editting cron entries via crontab.  See.
27
for praudit(1m) to give sensible output.  The following line needs to be
28
http://bugzilla.mindrot.org/show_bug.cgi?id=125
28
added to /etc/security/audit_event:
29
30
	32800:AUE_openssh:OpenSSH login:lo
31
32
If the contrib/buildpkg.sh script is used, the included postinstall
33
script will add the line for you.
34
35
The BSM audit event range available for third party TCB applications is
36
32768 - 65535.  Event number 32800 has been choosen for AUE_openssh.
37
There is no official registry of 3rd party event numbers, so if this
38
number is already in use on your system, you may change it at build time
39
by configure'ing --with-cflags=-DAUE_openssh=32801 then rebuilding.
40
29
41
30
$Id: README.platform,v 1.2 2004/04/23 08:57:13 dtucker Exp $
42
$Id: README.platform,v 1.2 2004/04/23 08:57:13 dtucker Exp $
(-)audit-bsm.c (+317 lines)
Added Link Here
1
/* $Id$ */
2
3
/*
4
 * TODO
5
 *
6
 * - deal with overlap between this and sys_auth_allowed_user
7
 *   sys_auth_record_login and record_failed_login.
8
 */
9
10
/*
11
 * Copyright 1988-2002 Sun Microsystems, Inc.  All rights reserved.
12
 * Use is subject to license terms.
13
 *
14
 *
15
 * Redistribution and use in source and binary forms, with or without
16
 * modification, are permitted provided that the following conditions
17
 * are met:
18
 * 1. Redistributions of source code must retain the above copyright
19
 *    notice, this list of conditions and the following disclaimer.
20
 * 2. Redistributions in binary form must reproduce the above copyright
21
 *    notice, this list of conditions and the following disclaimer in the
22
 *    documentation and/or other materials provided with the distribution.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
 *
35
 */
36
/* #pragma ident	"@(#)bsmaudit.c	1.1	01/09/17 SMI" */
37
38
#include "includes.h"
39
#if defined(USE_BSM_AUDIT)
40
41
#include "ssh.h"
42
#include "log.h"
43
#include "auth.h"
44
#include "xmalloc.h"
45
#include "audit-bsm.h"
46
47
#ifndef HAVE_GETTEXT
48
# define gettext(a)	(a)
49
#endif
50
51
extern Authctxt *the_authctxt;
52
53
#if 0
54
static char	*sav_cmd = NULL;
55
#endif
56
static AuditInfoTermID ssh_bsm_tid;
57
58
/* Below is the low-level BSM interface code */
59
60
/*
61
 * Check if the specified event is selected (enabled) for auditting.
62
 * Returns 1 if the event is selected, 0 if not and -1 on failure.
63
 */
64
static int
65
selected(char *username, uid_t uid, au_event_t event, int sf)
66
{
67
	int rc, sorf;
68
	char naflags[512];
69
	struct au_mask mask;
70
71
	mask.am_success = mask.am_failure = 0;
72
	if (uid < 0) {
73
		/* get flags for non-attributable (to a real user) events */
74
		rc = getacna(naflags, sizeof(naflags));
75
		if (rc == 0)
76
			(void) getauditflagsbin(naflags, &mask);
77
	} else
78
		rc = au_user_mask(username, &mask);
79
80
	sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
81
	return(au_preselect(event, &mask, sorf, AU_PRS_REREAD));
82
}
83
84
static void
85
bsm_audit_record(int typ, char *string, au_event_t event_no)
86
{
87
	int		ad, rc, sel;
88
	uid_t		uid = -1;
89
	gid_t		gid = -1;
90
	pid_t		pid = getpid();
91
	AuditInfoTermID	tid = ssh_bsm_tid;
92
93
	if (the_authctxt != NULL && the_authctxt->valid) {
94
		uid = the_authctxt->pw->pw_uid;
95
		gid = the_authctxt->pw->pw_gid;
96
	}
97
98
	rc = (typ == 0) ? 0 : -1;
99
	sel = selected(the_authctxt->user, uid, event_no, rc);
100
	debug3("BSM audit: typ %d rc %d \"%s\"", typ, rc, string);
101
	if (!sel)
102
		return;	/* audit event does not match mask, do not write */
103
104
	debug3("BSM audit: writing audit new record");
105
	ad = au_open();
106
107
	(void) au_write(ad, AUToSubjectFunc(uid, uid, gid, uid, gid,
108
	    pid, pid, &tid));
109
	(void) au_write(ad, au_to_text(string));
110
#if 0
111
	/*
112
	 * XXX: this seems wrong as it just attaches a text token to the
113
	 * logout containing the *last* command run.
114
	 */
115
	if (sav_cmd != NULL) {
116
		(void) au_write(ad, au_to_text(sav_cmd));
117
	}
118
#endif
119
	(void) au_write(ad, AUToReturnFunc(typ, rc));
120
121
	rc = au_close(ad, AU_TO_WRITE, event_no);
122
	if (rc < 0) {
123
		error("BSM audit: %s failed to write \"%s\" record: %s",
124
		    __func__, string, strerror(errno));
125
	}
126
}
127
128
static void
129
bsm_audit_session_setup(void)
130
{
131
	int rc;
132
	struct AuditInfoStruct info, now;
133
	au_mask_t mask;
134
135
	if (the_authctxt == NULL) {
136
		error("BSM audit: session setup internal error (NULL ctxt)");
137
		return;
138
	}
139
140
	if (the_authctxt->valid)
141
		info.ai_auid = the_authctxt->pw->pw_uid;
142
	else
143
		info.ai_auid = -1;
144
	info.ai_asid = getpid();
145
	mask.am_success = 0;
146
	mask.am_failure = 0;
147
148
	(void) au_user_mask(the_authctxt->user, &mask);
149
150
	info.ai_mask.am_success  = mask.am_success;
151
	info.ai_mask.am_failure  = mask.am_failure;
152
153
#if 0
154
	/* XXX: appears to be dead code?  "now" is not used */
155
	/* see if terminal id already set */
156
	if (GetAuditFunc(&now, sizeof(now)) < 0) {
157
		error("BSM audit: %s: %s failed: %s", __func__,
158
		    GetAuditFuncText, strerror(errno));
159
	}
160
#endif
161
162
	info.ai_termid = ssh_bsm_tid;
163
164
	rc = SetAuditFunc(&info, sizeof(info));
165
	if (rc < 0) {
166
		error("BSM audit: %s: %s failed: %s", __func__,
167
		    SetAuditFuncText, strerror(errno));
168
	}
169
}
170
171
172
static void
173
bsm_audit_bad_login(const char *what)
174
{
175
	char textbuf[BSM_TEXTBUFSZ];
176
177
	if (the_authctxt->valid) {
178
		(void) snprintf(textbuf, sizeof (textbuf),
179
			gettext("invalid %s for user %s"),
180
			    what, the_authctxt->user);
181
		bsm_audit_record(4, textbuf, AUE_openssh);
182
	} else {
183
		(void) snprintf(textbuf, sizeof (textbuf),
184
			gettext("invalid user name \"%s\""),
185
			    the_authctxt->user);
186
		bsm_audit_record(3, textbuf, AUE_openssh);
187
	}
188
}
189
190
/* Below is the sshd audit API code */
191
192
void
193
audit_connection_from(const char *host, int port)
194
{
195
	AuditInfoTermID *tid = &ssh_bsm_tid;
196
	char buf[1024];
197
198
	if (cannot_audit(0))
199
		return;
200
	debug3("BSM audit: connection from %.100s port %d", host, port);
201
202
	/* populate our terminal id structure */
203
#if defined(HAVE_GETAUDIT_ADDR)
204
	tid->at_port = (dev_t)port;
205
	aug_get_machine((char *)host, &(tid->at_addr[0]), &(tid->at_type));
206
	snprintf(buf, sizeof(buf), "%08x %08x %08x %08x", tid->at_addr[0],
207
	    tid->at_addr[1], tid->at_addr[2], tid->at_addr[3]);
208
	debug3("BSM audit: iptype %d machine ID %s", (int)tid->at_type, buf);
209
#else
210
	/* this is used on IPv4-only machines */
211
	tid->port = (dev_t)port;
212
	tid->machine = inet_addr(host);
213
	snprintf(buf, sizeof(buf), "%08x", tid->machine);
214
	debug3("BSM audit: machine ID %s", buf);
215
#endif
216
}
217
218
void
219
audit_run_command(const char *command)
220
{
221
	if (cannot_audit(0))
222
		return;
223
224
#if 0
225
	/*
226
	 * XXX: This seems wrong since at best it will only write the *last*
227
	 * command run to the audit log when sshd exits.
228
	 */
229
	if (sav_cmd != NULL) {
230
		free(sav_cmd);
231
		sav_cmd = NULL;
232
	}
233
	sav_cmd = xstrdup(command);
234
	debug3("BSM audit: sav_cmd=%s", sav_cmd);
235
#endif
236
}
237
238
void
239
audit_session_open(const char *ttyn)
240
{
241
	/* not implemented */
242
}
243
244
void
245
audit_session_close(const char *ttyn)
246
{
247
	/* not implemented */
248
}
249
250
void
251
audit_event(ssh_audit_event_t event)
252
{
253
	char    textbuf[BSM_TEXTBUFSZ];
254
	static int logged_in = 0;
255
	const char *user = the_authctxt ? the_authctxt->user : "(unknown user)";
256
257
	if (cannot_audit(0))
258
		return;
259
260
	switch(event) {
261
	case SSH_AUTH_SUCCESS:
262
		logged_in = 1;
263
		bsm_audit_session_setup();
264
		snprintf(textbuf, sizeof(textbuf),
265
		    gettext("successful login %s"), user);
266
		bsm_audit_record(0, textbuf, AUE_openssh);
267
		break;
268
269
	case SSH_CONNECTION_CLOSE:
270
		/*
271
		 * We can also get a close event if the user attempted auth
272
		 * but never succeeded.
273
		 */
274
		if (logged_in) {
275
			snprintf(textbuf, sizeof(textbuf),
276
			    gettext("sshd logout %s"), the_authctxt->user);
277
			bsm_audit_record(0, textbuf, AUE_logout);
278
		} else {
279
			debug("%s: connection closed without authentication",
280
			    __func__);
281
		}
282
		break;
283
284
	case SSH_NOLOGIN:
285
		bsm_audit_record(1,
286
		    gettext("logins disabled by /etc/nologin"), AUE_openssh);
287
		break;
288
289
	case SSH_LOGIN_EXCEED_MAXTRIES:
290
		snprintf(textbuf, sizeof(textbuf),
291
		    gettext("too many tries for user %s"), the_authctxt->user);
292
		bsm_audit_record(1, textbuf, AUE_openssh);
293
		break;
294
295
	case SSH_LOGIN_ROOT_DENIED:
296
		bsm_audit_record(2, gettext("not_console"), AUE_openssh);
297
		break;
298
299
	case SSH_AUTH_FAIL_PASSWD:
300
		bsm_audit_bad_login("password");
301
		break;
302
303
	case SSH_AUTH_FAIL_KBDINT:
304
		bsm_audit_bad_login("interactive password entry");
305
		break;
306
307
#if 0
308
	case SSH_AUTH_FAILED:
309
		bsm_audit_bad_login("authorization");
310
		break;
311
#endif
312
313
	default:
314
		debug("%s: unhandled event %d", __func__, event);
315
	}
316
}
317
#endif /* BSM */
(-)audit-bsm.h (+93 lines)
Added Link Here
1
/* $Id$ */
2
3
/*
4
 * Copyright 1988-2002 Sun Microsystems, Inc.  All rights reserved.
5
 * Use is subject to license terms.
6
 *
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 *
28
 */
29
/* #pragma ident	"@(#)bsmaudit.c	1.1	01/09/17 SMI" */
30
31
#include "includes.h"
32
#ifdef USE_BSM_AUDIT
33
34
#ifndef AUE_openssh
35
# define AUE_openssh     32800
36
#endif
37
#include <bsm/audit.h>
38
#include <bsm/libbsm.h>
39
#include <bsm/audit_uevents.h>
40
#include <bsm/audit_record.h>
41
#include <locale.h>
42
43
#if defined(HAVE_GETAUDIT_ADDR)
44
#define	AuditInfoStruct		auditinfo_addr
45
#define AuditInfoTermID		au_tid_addr_t
46
#define GetAuditFunc(a,b)	getaudit_addr((a),(b))
47
#define GetAuditFuncText	"getaudit_addr"
48
#define SetAuditFunc(a,b)	setaudit_addr((a),(b))
49
#define SetAuditFuncText	"setaudit_addr"
50
#define AUToSubjectFunc		au_to_subject_ex
51
#define AUToReturnFunc(a,b)	au_to_return32((a), (int32_t)(b))
52
#else
53
#define	AuditInfoStruct		auditinfo
54
#define AuditInfoTermID		au_tid_t
55
#define GetAuditFunc(a,b)	getaudit(a)
56
#define GetAuditFuncText	"getaudit"
57
#define SetAuditFunc(a,b)	setaudit(a)
58
#define SetAuditFuncText	"setaudit"
59
#define AUToSubjectFunc		au_to_subject
60
#define AUToReturnFunc(a,b)	au_to_return((a), (u_int)(b))
61
#endif
62
63
extern int	cannot_audit(int);
64
extern void	aug_init(void);
65
extern dev_t	aug_get_port(void);
66
extern int 	aug_get_machine(char *, u_int32_t *, u_int32_t *);
67
extern void	aug_save_auid(au_id_t);
68
extern void	aug_save_uid(uid_t);
69
extern void	aug_save_euid(uid_t);
70
extern void	aug_save_gid(gid_t);
71
extern void	aug_save_egid(gid_t);
72
extern void	aug_save_pid(pid_t);
73
extern void	aug_save_asid(au_asid_t);
74
extern void	aug_save_tid(dev_t, unsigned int);
75
extern void	aug_save_tid_ex(dev_t, u_int32_t *, u_int32_t);
76
extern int	aug_save_me(void);
77
extern int	aug_save_namask(void);
78
extern void	aug_save_event(au_event_t);
79
extern void	aug_save_sorf(int);
80
extern void	aug_save_text(char *);
81
extern void	aug_save_text1(char *);
82
extern void	aug_save_text2(char *);
83
extern void	aug_save_na(int);
84
extern void	aug_save_user(char *);
85
extern void	aug_save_path(char *);
86
extern int	aug_save_policy(void);
87
extern void	aug_save_afunc(int (*)(int));
88
extern int	aug_audit(void);
89
extern int	aug_na_selected(void);
90
extern int	aug_selected(void);
91
extern int	aug_daemon_session(void);
92
93
#endif
(-)configure.ac (+33 lines)
Lines 878-883 AC_ARG_WITH(libedit, Link Here
878
	fi ]
878
	fi ]
879
)
879
)
880
880
881
AUDIT_MODULE=none
882
AC_ARG_WITH(audit,
883
	[  --with-audit=module     Enable EXPERIMENTAL audit support (modules=debug,bsm)],
884
	[
885
	  AC_MSG_CHECKING(for supported audit module)
886
	  case "$withval" in
887
	  bsm)
888
		AC_MSG_RESULT(bsm)
889
		AUDIT_MODULE=bsm
890
		dnl    Checks for headers, libs and functions
891
		AC_CHECK_HEADERS(bsm/audit.h, [],
892
		    [AC_MSG_ERROR(BSM enabled and bsm/audit.h not found)])
893
		AC_CHECK_LIB(bsm, getaudit, [],
894
		    [AC_MSG_ERROR(BSM enabled and required library not found)])
895
		AC_CHECK_FUNCS(getaudit, [],
896
		    [AC_MSG_ERROR(BSM enabled and required function not found)])
897
		# These are optional
898
		AC_CHECK_FUNCS(getaudit_addr gettext)
899
		AC_DEFINE(USE_BSM_AUDIT, [], [Use BSM audit module])
900
		;;
901
	  debug)
902
		AUDIT_MODULE=debug
903
		AC_MSG_RESULT(debug)
904
		AC_DEFINE(SSH_AUDIT_EVENTS, [], Use audit debugging module)
905
		;;
906
	  *)
907
		AC_MSG_ERROR([Unknown audit module $withval])
908
		;;
909
	esac ]
910
)
911
881
dnl    Checks for library functions. Please keep in alphabetical order
912
dnl    Checks for library functions. Please keep in alphabetical order
882
AC_CHECK_FUNCS(\
913
AC_CHECK_FUNCS(\
883
	arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \
914
	arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \
Lines 1785-1790 TYPE_SOCKLEN_T Link Here
1785
1816
1786
AC_CHECK_TYPES(sig_atomic_t,,,[#include <signal.h>])
1817
AC_CHECK_TYPES(sig_atomic_t,,,[#include <signal.h>])
1787
1818
1819
AC_CHECK_TYPES(in_addr_t,,,[#include <netinet/in.h>])
1820
1788
AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [
1821
AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [
1789
	AC_TRY_COMPILE(
1822
	AC_TRY_COMPILE(
1790
		[
1823
		[
(-)defines.h (+9 lines)
Lines 288-293 struct sockaddr_un { Link Here
288
};
288
};
289
#endif /* HAVE_SYS_UN_H */
289
#endif /* HAVE_SYS_UN_H */
290
290
291
#ifndef HAVE_IN_ADDR_T
292
typedef u_int32_t	in_addr_t;
293
#endif
294
291
#if defined(BROKEN_SYS_TERMIO_H) && !defined(_STRUCT_WINSIZE)
295
#if defined(BROKEN_SYS_TERMIO_H) && !defined(_STRUCT_WINSIZE)
292
#define _STRUCT_WINSIZE
296
#define _STRUCT_WINSIZE
293
struct winsize {
297
struct winsize {
Lines 530-535 struct winsize { Link Here
530
# define getpgrp() getpgrp(0)
534
# define getpgrp() getpgrp(0)
531
#endif
535
#endif
532
536
537
#ifdef USE_BSM_AUDIT
538
# define SSH_AUDIT_EVENTS
539
# define CUSTOM_SSH_AUDIT_EVENTS
540
#endif
541
533
/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */
542
/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */
534
#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f)
543
#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f)
535
# define OPENSSL_free(x) Free(x)
544
# define OPENSSL_free(x) Free(x)

Return to bug 125