1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1999 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate * All rights reserved.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate * This file contains all authentication-related functionality for
31*7c478bd9Sstevel@tonic-gate * SLP. Two interfaces are exported:
32*7c478bd9Sstevel@tonic-gate *
33*7c478bd9Sstevel@tonic-gate * slp_sign: Creates auth blocks for a given piece of data
34*7c478bd9Sstevel@tonic-gate * slp_verify: Verifies an auth block for a given piece of data.
35*7c478bd9Sstevel@tonic-gate *
36*7c478bd9Sstevel@tonic-gate * A shared object which provides crypto-suites and key management
37*7c478bd9Sstevel@tonic-gate * functionality is dynamically linked in during intialization. If
38*7c478bd9Sstevel@tonic-gate * the shared object cannot be found, the authentication code aborts
39*7c478bd9Sstevel@tonic-gate * and an SLP_AUTHENTICATION_FAILED error is returned. Which shared
40*7c478bd9Sstevel@tonic-gate * object is actually loaded is controlled by the property
41*7c478bd9Sstevel@tonic-gate * sun.net.slp.authBackend; the value of this property should contain
42*7c478bd9Sstevel@tonic-gate * either the name of a shared object which implements the necessary
43*7c478bd9Sstevel@tonic-gate * interfaces, or a full or relative path to such an object. This value
44*7c478bd9Sstevel@tonic-gate * will be passed to dlopen(3X) to resolve the symbols.
45*7c478bd9Sstevel@tonic-gate *
46*7c478bd9Sstevel@tonic-gate * The shared object must implement the following AMI interfaces:
47*7c478bd9Sstevel@tonic-gate *
48*7c478bd9Sstevel@tonic-gate * ami_init
49*7c478bd9Sstevel@tonic-gate * ami_sign
50*7c478bd9Sstevel@tonic-gate * ami_verify
51*7c478bd9Sstevel@tonic-gate * ami_get_cert
52*7c478bd9Sstevel@tonic-gate * ami_get_cert_chain
53*7c478bd9Sstevel@tonic-gate * ami_strerror
54*7c478bd9Sstevel@tonic-gate * ami_end
55*7c478bd9Sstevel@tonic-gate * AMI_MD5WithRSAEncryption_AID
56*7c478bd9Sstevel@tonic-gate * AMI_SHA1WithDSASignature_AID
57*7c478bd9Sstevel@tonic-gate *
58*7c478bd9Sstevel@tonic-gate * See security/ami.h for more info on these interfaces.
59*7c478bd9Sstevel@tonic-gate */
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gate #include <stdio.h>
62*7c478bd9Sstevel@tonic-gate #include <string.h>
63*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
64*7c478bd9Sstevel@tonic-gate #include <syslog.h>
65*7c478bd9Sstevel@tonic-gate #include <synch.h>
66*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
67*7c478bd9Sstevel@tonic-gate #include <slp-internal.h>
68*7c478bd9Sstevel@tonic-gate #include "slp_ami.h"
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate /* Prototypes for dynamically loaded (dl'd) AMI functions */
71*7c478bd9Sstevel@tonic-gate static ami_algid **ami_rsa_aid, **ami_dsa_aid;
72*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_init)(ami_handle_t **, const char *,
73*7c478bd9Sstevel@tonic-gate const char *, const u_int, const u_int,
74*7c478bd9Sstevel@tonic-gate const char *);
75*7c478bd9Sstevel@tonic-gate
76*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_sign)(ami_handle_t *,
77*7c478bd9Sstevel@tonic-gate const uchar_t *,
78*7c478bd9Sstevel@tonic-gate const size_t,
79*7c478bd9Sstevel@tonic-gate const int,
80*7c478bd9Sstevel@tonic-gate const ami_algid *,
81*7c478bd9Sstevel@tonic-gate const uchar_t *,
82*7c478bd9Sstevel@tonic-gate const size_t,
83*7c478bd9Sstevel@tonic-gate const ami_algid *,
84*7c478bd9Sstevel@tonic-gate uchar_t **,
85*7c478bd9Sstevel@tonic-gate size_t *);
86*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_verify)(ami_handle_t *,
87*7c478bd9Sstevel@tonic-gate const uchar_t *,
88*7c478bd9Sstevel@tonic-gate const size_t,
89*7c478bd9Sstevel@tonic-gate const int,
90*7c478bd9Sstevel@tonic-gate const ami_algid *,
91*7c478bd9Sstevel@tonic-gate const uchar_t *,
92*7c478bd9Sstevel@tonic-gate const size_t,
93*7c478bd9Sstevel@tonic-gate const ami_algid *,
94*7c478bd9Sstevel@tonic-gate const uchar_t *,
95*7c478bd9Sstevel@tonic-gate const size_t);
96*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_get_cert)(const ami_handle_t *,
97*7c478bd9Sstevel@tonic-gate const char *,
98*7c478bd9Sstevel@tonic-gate ami_cert **,
99*7c478bd9Sstevel@tonic-gate int *);
100*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_get_cert_chain)(const ami_handle_t *,
101*7c478bd9Sstevel@tonic-gate const ami_cert *,
102*7c478bd9Sstevel@tonic-gate const char **,
103*7c478bd9Sstevel@tonic-gate int flags,
104*7c478bd9Sstevel@tonic-gate ami_cert **,
105*7c478bd9Sstevel@tonic-gate int *);
106*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_str2dn)(const ami_handle_t *,
107*7c478bd9Sstevel@tonic-gate char *, ami_name **);
108*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_dn2str)(const ami_handle_t *,
109*7c478bd9Sstevel@tonic-gate ami_name *, char **);
110*7c478bd9Sstevel@tonic-gate static void (*dld_ami_free_cert_list)(ami_cert **, int);
111*7c478bd9Sstevel@tonic-gate static void (*dld_ami_free_dn)(ami_name **);
112*7c478bd9Sstevel@tonic-gate static char *(*dld_ami_strerror)(const ami_handle_t *, const AMI_STATUS);
113*7c478bd9Sstevel@tonic-gate static AMI_STATUS (*dld_ami_end)(ami_handle_t *);
114*7c478bd9Sstevel@tonic-gate
115*7c478bd9Sstevel@tonic-gate /* local utilities */
116*7c478bd9Sstevel@tonic-gate static SLPError get_security_backend();
117*7c478bd9Sstevel@tonic-gate static SLPError make_tbs(const char *, struct iovec *, int,
118*7c478bd9Sstevel@tonic-gate unsigned int, unsigned char **, size_t *);
119*7c478bd9Sstevel@tonic-gate static SLPError make_authblock(struct iovec *, int, const char *,
120*7c478bd9Sstevel@tonic-gate time_t, caddr_t *, size_t *);
121*7c478bd9Sstevel@tonic-gate static SLPError do_verify(unsigned char *, size_t, unsigned short,
122*7c478bd9Sstevel@tonic-gate const unsigned char *, size_t, const char *);
123*7c478bd9Sstevel@tonic-gate static char *alias2dn(ami_handle_t *);
124*7c478bd9Sstevel@tonic-gate static SLPError check_spis(ami_handle_t *, ami_cert *, int, const char *);
125*7c478bd9Sstevel@tonic-gate static int dncmp(ami_handle_t *, const char *, const char *);
126*7c478bd9Sstevel@tonic-gate
127*7c478bd9Sstevel@tonic-gate /*
128*7c478bd9Sstevel@tonic-gate * Creates a cryptographic signature over the components of authiov, and
129*7c478bd9Sstevel@tonic-gate * creates an auth block from the signature. The auth block is placed
130*7c478bd9Sstevel@tonic-gate * into msgiov at the index specified by msgiov_index. The timestamp
131*7c478bd9Sstevel@tonic-gate * for the auth block is given in ts. Caller must free the auth block
132*7c478bd9Sstevel@tonic-gate * when finished.
133*7c478bd9Sstevel@tonic-gate *
134*7c478bd9Sstevel@tonic-gate * Returns SLP_OK on success, SLP_AUTHENTICATION_FAILED on failure.
135*7c478bd9Sstevel@tonic-gate */
slp_sign(struct iovec * authiov,int authiov_len,time_t ts,struct iovec * msgiov,int msg_index)136*7c478bd9Sstevel@tonic-gate SLPError slp_sign(struct iovec *authiov, int authiov_len, time_t ts,
137*7c478bd9Sstevel@tonic-gate struct iovec *msgiov, int msg_index) {
138*7c478bd9Sstevel@tonic-gate
139*7c478bd9Sstevel@tonic-gate char *sign_as = NULL;
140*7c478bd9Sstevel@tonic-gate char *alias, *aliasp;
141*7c478bd9Sstevel@tonic-gate SLPError err = SLP_OK;
142*7c478bd9Sstevel@tonic-gate unsigned char num_auths = 0;
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate /* This auth block is always at least 1 byte long, for num auths */
145*7c478bd9Sstevel@tonic-gate msgiov[msg_index].iov_base = calloc(1, 1);
146*7c478bd9Sstevel@tonic-gate msgiov[msg_index].iov_len = 1;
147*7c478bd9Sstevel@tonic-gate
148*7c478bd9Sstevel@tonic-gate /* if security is off, just return the empty auth block */
149*7c478bd9Sstevel@tonic-gate if (!slp_get_security_on() || slp_get_bypass_auth()) {
150*7c478bd9Sstevel@tonic-gate return (SLP_OK);
151*7c478bd9Sstevel@tonic-gate }
152*7c478bd9Sstevel@tonic-gate
153*7c478bd9Sstevel@tonic-gate /*
154*7c478bd9Sstevel@tonic-gate * Security is disabled in Solaris 8 due to AMI trouble.
155*7c478bd9Sstevel@tonic-gate * The pragmas and LINTED suppress "statement not reached"
156*7c478bd9Sstevel@tonic-gate * compiler and lint warnings, and should be removed when
157*7c478bd9Sstevel@tonic-gate * security is re-enabled.
158*7c478bd9Sstevel@tonic-gate */
159*7c478bd9Sstevel@tonic-gate return (SLP_SECURITY_UNAVAILABLE);
160*7c478bd9Sstevel@tonic-gate
161*7c478bd9Sstevel@tonic-gate #pragma error_messages(off, E_STATEMENT_NOT_REACHED)
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate /* else we should sign this advert */
164*7c478bd9Sstevel@tonic-gate if (!(sign_as = (char *)SLPGetProperty(SLP_CONFIG_SIGN_AS)) ||
165*7c478bd9Sstevel@tonic-gate /*LINTED statement not reached*/
166*7c478bd9Sstevel@tonic-gate !*sign_as) {
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "slp_sign", "No signing identity given");
169*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
170*7c478bd9Sstevel@tonic-gate }
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate /* Try to initialize security backend */
173*7c478bd9Sstevel@tonic-gate if (!(err = get_security_backend()) == SLP_OK) {
174*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate
177*7c478bd9Sstevel@tonic-gate /* dup SPI list so we can destructively modify it */
178*7c478bd9Sstevel@tonic-gate if (!(sign_as = strdup(sign_as))) {
179*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_sign", "out of memory");
180*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate /* For each SPI, create an auth block */
184*7c478bd9Sstevel@tonic-gate for (aliasp = sign_as; aliasp; ) {
185*7c478bd9Sstevel@tonic-gate alias = aliasp;
186*7c478bd9Sstevel@tonic-gate aliasp = slp_utf_strchr(aliasp, ',');
187*7c478bd9Sstevel@tonic-gate if (aliasp) {
188*7c478bd9Sstevel@tonic-gate *aliasp++ = 0;
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate
191*7c478bd9Sstevel@tonic-gate /* create an auth block for this SPI */
192*7c478bd9Sstevel@tonic-gate err = make_authblock(authiov, authiov_len, alias, ts,
193*7c478bd9Sstevel@tonic-gate &(msgiov[msg_index].iov_base),
194*7c478bd9Sstevel@tonic-gate (size_t *)&(msgiov[msg_index].iov_len));
195*7c478bd9Sstevel@tonic-gate if (err == SLP_MEMORY_ALLOC_FAILED) {
196*7c478bd9Sstevel@tonic-gate goto done;
197*7c478bd9Sstevel@tonic-gate } else if (err != SLP_OK) {
198*7c478bd9Sstevel@tonic-gate /* else skip and keep going */
199*7c478bd9Sstevel@tonic-gate continue;
200*7c478bd9Sstevel@tonic-gate }
201*7c478bd9Sstevel@tonic-gate
202*7c478bd9Sstevel@tonic-gate num_auths++;
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate
205*7c478bd9Sstevel@tonic-gate done:
206*7c478bd9Sstevel@tonic-gate if (sign_as) free(sign_as);
207*7c478bd9Sstevel@tonic-gate
208*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) {
209*7c478bd9Sstevel@tonic-gate return (err);
210*7c478bd9Sstevel@tonic-gate }
211*7c478bd9Sstevel@tonic-gate
212*7c478bd9Sstevel@tonic-gate if (num_auths == 0) {
213*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
214*7c478bd9Sstevel@tonic-gate } else {
215*7c478bd9Sstevel@tonic-gate size_t off = 0;
216*7c478bd9Sstevel@tonic-gate /* Lay in number of auth blocks created */
217*7c478bd9Sstevel@tonic-gate err = slp_add_byte(msgiov[msg_index].iov_base, 1, num_auths, &off);
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate return (err);
221*7c478bd9Sstevel@tonic-gate #pragma error_messages(on, E_STATEMENT_NOT_REACHED)
222*7c478bd9Sstevel@tonic-gate }
223*7c478bd9Sstevel@tonic-gate
224*7c478bd9Sstevel@tonic-gate /*
225*7c478bd9Sstevel@tonic-gate * Verifies that the signature(s) contained in authblocks validates
226*7c478bd9Sstevel@tonic-gate * the data in authiov. slp_verify will not read more than len bytes
227*7c478bd9Sstevel@tonic-gate * from authblocks. n is the stated number of authblocks in authblock.
228*7c478bd9Sstevel@tonic-gate * The total length of all auth blocks read is placed in *total.
229*7c478bd9Sstevel@tonic-gate *
230*7c478bd9Sstevel@tonic-gate * Returns SLP_OK if the verification succeeds.
231*7c478bd9Sstevel@tonic-gate */
slp_verify(struct iovec * authiov,int authiov_len,const char * authblocks,size_t len,int n,size_t * total)232*7c478bd9Sstevel@tonic-gate SLPError slp_verify(struct iovec *authiov, int authiov_len,
233*7c478bd9Sstevel@tonic-gate const char *authblocks, size_t len, int n, size_t *total) {
234*7c478bd9Sstevel@tonic-gate int i;
235*7c478bd9Sstevel@tonic-gate size_t off, this_ab;
236*7c478bd9Sstevel@tonic-gate unsigned short bsd, ablen;
237*7c478bd9Sstevel@tonic-gate unsigned int timestamp;
238*7c478bd9Sstevel@tonic-gate char *spi = NULL;
239*7c478bd9Sstevel@tonic-gate SLPError err = SLP_AUTHENTICATION_FAILED;
240*7c478bd9Sstevel@tonic-gate unsigned char *inbytes = NULL;
241*7c478bd9Sstevel@tonic-gate size_t inbytes_len;
242*7c478bd9Sstevel@tonic-gate unsigned char *sig;
243*7c478bd9Sstevel@tonic-gate size_t siglen;
244*7c478bd9Sstevel@tonic-gate
245*7c478bd9Sstevel@tonic-gate /* 1st: if bypass_auth == true, just return SLP_OK */
246*7c478bd9Sstevel@tonic-gate if (slp_get_bypass_auth()) {
247*7c478bd9Sstevel@tonic-gate return (SLP_OK);
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate
250*7c478bd9Sstevel@tonic-gate /* 2nd: If security is off, and there are no auth blocks, OK */
251*7c478bd9Sstevel@tonic-gate if (!slp_get_security_on() && n == 0) {
252*7c478bd9Sstevel@tonic-gate return (SLP_OK);
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate /*
256*7c478bd9Sstevel@tonic-gate * Security is disabled in Solaris 8 due to AMI trouble.
257*7c478bd9Sstevel@tonic-gate * The pragmas and LINTED suppress "statement not reached"
258*7c478bd9Sstevel@tonic-gate * compiler and lint warnings, and should be removed when
259*7c478bd9Sstevel@tonic-gate * security is re-enabled.
260*7c478bd9Sstevel@tonic-gate */
261*7c478bd9Sstevel@tonic-gate return (SLP_SECURITY_UNAVAILABLE);
262*7c478bd9Sstevel@tonic-gate #pragma error_messages(off, E_STATEMENT_NOT_REACHED)
263*7c478bd9Sstevel@tonic-gate
264*7c478bd9Sstevel@tonic-gate /* For all other scenarios, we must verify the auth blocks */
265*7c478bd9Sstevel@tonic-gate /*LINTED statement not reached*/
266*7c478bd9Sstevel@tonic-gate if (get_security_backend() != SLP_OK || n == 0) {
267*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
268*7c478bd9Sstevel@tonic-gate }
269*7c478bd9Sstevel@tonic-gate
270*7c478bd9Sstevel@tonic-gate /*
271*7c478bd9Sstevel@tonic-gate * If we get here, the backend is available and there are auth
272*7c478bd9Sstevel@tonic-gate * blocks to verify. Verify each input auth block.
273*7c478bd9Sstevel@tonic-gate */
274*7c478bd9Sstevel@tonic-gate off = 0; /* offset into raw auth blocks */
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate for (i = 0; i < n && off <= len; i++) {
277*7c478bd9Sstevel@tonic-gate this_ab = off;
278*7c478bd9Sstevel@tonic-gate
279*7c478bd9Sstevel@tonic-gate /* BSD */
280*7c478bd9Sstevel@tonic-gate if ((err = slp_get_sht(authblocks, len, &off, &bsd)) != SLP_OK) {
281*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "slp_verify", "corrupt auth block");
282*7c478bd9Sstevel@tonic-gate goto done;
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate
285*7c478bd9Sstevel@tonic-gate /* Auth block length */
286*7c478bd9Sstevel@tonic-gate if ((err = slp_get_sht(authblocks, len, &off, &ablen)) != SLP_OK) {
287*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "slp_verify", "corrupt auth block");
288*7c478bd9Sstevel@tonic-gate goto done;
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate
291*7c478bd9Sstevel@tonic-gate /* Time stamp */
292*7c478bd9Sstevel@tonic-gate if ((err = slp_get_int32(authblocks, len, &off, ×tamp))
293*7c478bd9Sstevel@tonic-gate != SLP_OK) {
294*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "slp_verify", "corrupt auth block");
295*7c478bd9Sstevel@tonic-gate goto done;
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate
298*7c478bd9Sstevel@tonic-gate /* SPI string */
299*7c478bd9Sstevel@tonic-gate if ((err = slp_get_string(authblocks, len, &off, &spi))
300*7c478bd9Sstevel@tonic-gate != SLP_OK) {
301*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "slp_verify", "corrupt auth block");
302*7c478bd9Sstevel@tonic-gate goto done;
303*7c478bd9Sstevel@tonic-gate }
304*7c478bd9Sstevel@tonic-gate
305*7c478bd9Sstevel@tonic-gate err = make_tbs(
306*7c478bd9Sstevel@tonic-gate spi, authiov, authiov_len, timestamp, &inbytes, &inbytes_len);
307*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) {
308*7c478bd9Sstevel@tonic-gate goto done;
309*7c478bd9Sstevel@tonic-gate }
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate sig = (unsigned char *)(authblocks + off);
312*7c478bd9Sstevel@tonic-gate siglen = ablen - (off - this_ab);
313*7c478bd9Sstevel@tonic-gate
314*7c478bd9Sstevel@tonic-gate off += siglen;
315*7c478bd9Sstevel@tonic-gate
316*7c478bd9Sstevel@tonic-gate err = do_verify(inbytes, inbytes_len, bsd, sig, siglen, spi);
317*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) {
318*7c478bd9Sstevel@tonic-gate free(spi);
319*7c478bd9Sstevel@tonic-gate goto done;
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate free(spi);
323*7c478bd9Sstevel@tonic-gate }
324*7c478bd9Sstevel@tonic-gate
325*7c478bd9Sstevel@tonic-gate done:
326*7c478bd9Sstevel@tonic-gate if (inbytes) free(inbytes);
327*7c478bd9Sstevel@tonic-gate *total = off;
328*7c478bd9Sstevel@tonic-gate
329*7c478bd9Sstevel@tonic-gate return (err);
330*7c478bd9Sstevel@tonic-gate #pragma error_messages(on, E_STATEMENT_NOT_REACHED)
331*7c478bd9Sstevel@tonic-gate }
332*7c478bd9Sstevel@tonic-gate
333*7c478bd9Sstevel@tonic-gate /*
334*7c478bd9Sstevel@tonic-gate * When first called, attempts to dlopen a security shared library
335*7c478bd9Sstevel@tonic-gate * and dlsym in the necessary interfaces. The library remains mapped
336*7c478bd9Sstevel@tonic-gate * in, so successive calls just return SLP_OK.
337*7c478bd9Sstevel@tonic-gate */
get_security_backend()338*7c478bd9Sstevel@tonic-gate static SLPError get_security_backend() {
339*7c478bd9Sstevel@tonic-gate static mutex_t be_lock = DEFAULTMUTEX;
340*7c478bd9Sstevel@tonic-gate static void *dl = NULL;
341*7c478bd9Sstevel@tonic-gate static int got_backend = 0;
342*7c478bd9Sstevel@tonic-gate SLPError err = SLP_SECURITY_UNAVAILABLE;
343*7c478bd9Sstevel@tonic-gate const char *libname;
344*7c478bd9Sstevel@tonic-gate char *dlerr;
345*7c478bd9Sstevel@tonic-gate
346*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&be_lock);
347*7c478bd9Sstevel@tonic-gate
348*7c478bd9Sstevel@tonic-gate if (got_backend) {
349*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&be_lock);
350*7c478bd9Sstevel@tonic-gate return (SLP_OK);
351*7c478bd9Sstevel@tonic-gate }
352*7c478bd9Sstevel@tonic-gate
353*7c478bd9Sstevel@tonic-gate if (!(libname = SLPGetProperty(SLP_CONFIG_AUTH_BACKEND)) ||
354*7c478bd9Sstevel@tonic-gate !*libname) {
355*7c478bd9Sstevel@tonic-gate /* revert to default */
356*7c478bd9Sstevel@tonic-gate libname = "libami.so.1";
357*7c478bd9Sstevel@tonic-gate }
358*7c478bd9Sstevel@tonic-gate
359*7c478bd9Sstevel@tonic-gate if (!(dl = dlopen(libname, RTLD_LAZY))) {
360*7c478bd9Sstevel@tonic-gate dlerr = dlerror();
361*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
362*7c478bd9Sstevel@tonic-gate "Could not dlopen AMI library: %s",
363*7c478bd9Sstevel@tonic-gate (dlerr ? dlerr : "unknown DL error"));
364*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
365*7c478bd9Sstevel@tonic-gate "Is AMI installed?");
366*7c478bd9Sstevel@tonic-gate goto done;
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate
369*7c478bd9Sstevel@tonic-gate /* Relocate AMI's statically initialized AIDs we need */
370*7c478bd9Sstevel@tonic-gate if (!(ami_rsa_aid =
371*7c478bd9Sstevel@tonic-gate dlsym(dl, "AMI_MD5WithRSAEncryption_AID"))) {
372*7c478bd9Sstevel@tonic-gate
373*7c478bd9Sstevel@tonic-gate dlerr = dlerror();
374*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
375*7c478bd9Sstevel@tonic-gate "Could not relocate AMI_MD5WithRSAEncryption_AID: %s",
376*7c478bd9Sstevel@tonic-gate (dlerr ? dlerr : "unknown DL error"));
377*7c478bd9Sstevel@tonic-gate goto done;
378*7c478bd9Sstevel@tonic-gate }
379*7c478bd9Sstevel@tonic-gate
380*7c478bd9Sstevel@tonic-gate if (!(ami_dsa_aid =
381*7c478bd9Sstevel@tonic-gate dlsym(dl, "AMI_SHA1WithDSASignature_AID"))) {
382*7c478bd9Sstevel@tonic-gate
383*7c478bd9Sstevel@tonic-gate dlerr = dlerror();
384*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
385*7c478bd9Sstevel@tonic-gate "Could not relocate AMI_SHA1WithDSASignature_AID: %s",
386*7c478bd9Sstevel@tonic-gate (dlerr ? dlerr : "unknown DL error"));
387*7c478bd9Sstevel@tonic-gate goto done;
388*7c478bd9Sstevel@tonic-gate }
389*7c478bd9Sstevel@tonic-gate
390*7c478bd9Sstevel@tonic-gate /* Bring in the functions we need */
391*7c478bd9Sstevel@tonic-gate if (!(dld_ami_init = (AMI_STATUS (*)(ami_handle_t **,
392*7c478bd9Sstevel@tonic-gate const char *,
393*7c478bd9Sstevel@tonic-gate const char *,
394*7c478bd9Sstevel@tonic-gate const u_int,
395*7c478bd9Sstevel@tonic-gate const u_int,
396*7c478bd9Sstevel@tonic-gate const char *))dlsym(
397*7c478bd9Sstevel@tonic-gate dl, "ami_init"))) {
398*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
399*7c478bd9Sstevel@tonic-gate "Could not load ami_init");
400*7c478bd9Sstevel@tonic-gate goto done;
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate
403*7c478bd9Sstevel@tonic-gate if (!(dld_ami_sign = (AMI_STATUS (*)(ami_handle_t *,
404*7c478bd9Sstevel@tonic-gate const uchar_t *,
405*7c478bd9Sstevel@tonic-gate const size_t,
406*7c478bd9Sstevel@tonic-gate const int,
407*7c478bd9Sstevel@tonic-gate const ami_algid *,
408*7c478bd9Sstevel@tonic-gate const uchar_t *,
409*7c478bd9Sstevel@tonic-gate const size_t,
410*7c478bd9Sstevel@tonic-gate const ami_algid *,
411*7c478bd9Sstevel@tonic-gate uchar_t **,
412*7c478bd9Sstevel@tonic-gate size_t *))dlsym(
413*7c478bd9Sstevel@tonic-gate dl, "ami_sign"))) {
414*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
415*7c478bd9Sstevel@tonic-gate "Could not load ami_sign");
416*7c478bd9Sstevel@tonic-gate goto done;
417*7c478bd9Sstevel@tonic-gate }
418*7c478bd9Sstevel@tonic-gate
419*7c478bd9Sstevel@tonic-gate if (!(dld_ami_verify = (AMI_STATUS (*)(ami_handle_t *,
420*7c478bd9Sstevel@tonic-gate const uchar_t *,
421*7c478bd9Sstevel@tonic-gate const size_t,
422*7c478bd9Sstevel@tonic-gate const int,
423*7c478bd9Sstevel@tonic-gate const ami_algid *,
424*7c478bd9Sstevel@tonic-gate const uchar_t *,
425*7c478bd9Sstevel@tonic-gate const size_t,
426*7c478bd9Sstevel@tonic-gate const ami_algid *,
427*7c478bd9Sstevel@tonic-gate const uchar_t *,
428*7c478bd9Sstevel@tonic-gate const size_t))dlsym(
429*7c478bd9Sstevel@tonic-gate dl, "ami_verify"))) {
430*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
431*7c478bd9Sstevel@tonic-gate "Could not load ami_verify");
432*7c478bd9Sstevel@tonic-gate goto done;
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate
435*7c478bd9Sstevel@tonic-gate if (!(dld_ami_get_cert = (AMI_STATUS (*)(const ami_handle_t *,
436*7c478bd9Sstevel@tonic-gate const char *,
437*7c478bd9Sstevel@tonic-gate ami_cert **,
438*7c478bd9Sstevel@tonic-gate int *))dlsym(
439*7c478bd9Sstevel@tonic-gate dl, "ami_get_cert"))) {
440*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
441*7c478bd9Sstevel@tonic-gate "Could not load ami_get_cert");
442*7c478bd9Sstevel@tonic-gate goto done;
443*7c478bd9Sstevel@tonic-gate }
444*7c478bd9Sstevel@tonic-gate
445*7c478bd9Sstevel@tonic-gate if (!(dld_ami_get_cert_chain = (AMI_STATUS (*)(const ami_handle_t *,
446*7c478bd9Sstevel@tonic-gate const ami_cert *,
447*7c478bd9Sstevel@tonic-gate const char **,
448*7c478bd9Sstevel@tonic-gate int flags,
449*7c478bd9Sstevel@tonic-gate ami_cert **,
450*7c478bd9Sstevel@tonic-gate int *))dlsym(
451*7c478bd9Sstevel@tonic-gate dl, "ami_get_cert_chain"))) {
452*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
453*7c478bd9Sstevel@tonic-gate "Could not load ami_get_cert_chain");
454*7c478bd9Sstevel@tonic-gate goto done;
455*7c478bd9Sstevel@tonic-gate }
456*7c478bd9Sstevel@tonic-gate
457*7c478bd9Sstevel@tonic-gate if (!(dld_ami_str2dn = (AMI_STATUS (*)(const ami_handle_t *,
458*7c478bd9Sstevel@tonic-gate char *, ami_name **))dlsym(
459*7c478bd9Sstevel@tonic-gate dl, "ami_str2dn"))) {
460*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
461*7c478bd9Sstevel@tonic-gate "Could not load ami_str2dn");
462*7c478bd9Sstevel@tonic-gate goto done;
463*7c478bd9Sstevel@tonic-gate }
464*7c478bd9Sstevel@tonic-gate
465*7c478bd9Sstevel@tonic-gate if (!(dld_ami_dn2str = (AMI_STATUS (*)(const ami_handle_t *,
466*7c478bd9Sstevel@tonic-gate ami_name *, char **))dlsym(
467*7c478bd9Sstevel@tonic-gate dl, "ami_dn2str"))) {
468*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
469*7c478bd9Sstevel@tonic-gate "Could not load ami_dn2str");
470*7c478bd9Sstevel@tonic-gate goto done;
471*7c478bd9Sstevel@tonic-gate }
472*7c478bd9Sstevel@tonic-gate
473*7c478bd9Sstevel@tonic-gate if (!(dld_ami_free_cert_list = (void (*)(ami_cert **, int))dlsym(
474*7c478bd9Sstevel@tonic-gate dl, "ami_free_cert_list"))) {
475*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
476*7c478bd9Sstevel@tonic-gate "Could not load ami_free_cert_list");
477*7c478bd9Sstevel@tonic-gate goto done;
478*7c478bd9Sstevel@tonic-gate }
479*7c478bd9Sstevel@tonic-gate
480*7c478bd9Sstevel@tonic-gate if (!(dld_ami_free_dn = (void (*)(ami_name **))dlsym(
481*7c478bd9Sstevel@tonic-gate dl, "ami_free_dn"))) {
482*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
483*7c478bd9Sstevel@tonic-gate "Could not load ami_free_dn");
484*7c478bd9Sstevel@tonic-gate goto done;
485*7c478bd9Sstevel@tonic-gate }
486*7c478bd9Sstevel@tonic-gate
487*7c478bd9Sstevel@tonic-gate if (!(dld_ami_strerror = (char *(*)(const ami_handle_t *,
488*7c478bd9Sstevel@tonic-gate const AMI_STATUS))dlsym(
489*7c478bd9Sstevel@tonic-gate dl, "ami_strerror"))) {
490*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
491*7c478bd9Sstevel@tonic-gate "Could not load ami_strerror");
492*7c478bd9Sstevel@tonic-gate goto done;
493*7c478bd9Sstevel@tonic-gate }
494*7c478bd9Sstevel@tonic-gate
495*7c478bd9Sstevel@tonic-gate if (!(dld_ami_end = (AMI_STATUS (*)(ami_handle_t *))dlsym(
496*7c478bd9Sstevel@tonic-gate dl, "ami_end"))) {
497*7c478bd9Sstevel@tonic-gate
498*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "get_security_backend",
499*7c478bd9Sstevel@tonic-gate "Could not load ami_end");
500*7c478bd9Sstevel@tonic-gate goto done;
501*7c478bd9Sstevel@tonic-gate }
502*7c478bd9Sstevel@tonic-gate
503*7c478bd9Sstevel@tonic-gate got_backend = 1;
504*7c478bd9Sstevel@tonic-gate err = SLP_OK;
505*7c478bd9Sstevel@tonic-gate
506*7c478bd9Sstevel@tonic-gate done:
507*7c478bd9Sstevel@tonic-gate if (!got_backend && dl) {
508*7c478bd9Sstevel@tonic-gate (void) dlclose(dl);
509*7c478bd9Sstevel@tonic-gate }
510*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&be_lock);
511*7c478bd9Sstevel@tonic-gate
512*7c478bd9Sstevel@tonic-gate return (err);
513*7c478bd9Sstevel@tonic-gate }
514*7c478bd9Sstevel@tonic-gate
515*7c478bd9Sstevel@tonic-gate /*
516*7c478bd9Sstevel@tonic-gate * Creates a bytes to-be-signed buffer suitable for input
517*7c478bd9Sstevel@tonic-gate * a signature algorithm.
518*7c478bd9Sstevel@tonic-gate *
519*7c478bd9Sstevel@tonic-gate * The only backend currently available is AMI, which does
520*7c478bd9Sstevel@tonic-gate * not support incremental updates for digesting. Hence we
521*7c478bd9Sstevel@tonic-gate * must copy all elements of the input iovec into one buffer.
522*7c478bd9Sstevel@tonic-gate *
523*7c478bd9Sstevel@tonic-gate * This function allocates a single buffer into *buf big enough
524*7c478bd9Sstevel@tonic-gate * to hold all necessary elements, sets *buflen to this length, and
525*7c478bd9Sstevel@tonic-gate * makes a bytes-to-be-signed buffer. Into this buffer is placed
526*7c478bd9Sstevel@tonic-gate * first the SPI string, then all elements of iov, and finally
527*7c478bd9Sstevel@tonic-gate * the timestamp. Caller must free *buf.
528*7c478bd9Sstevel@tonic-gate *
529*7c478bd9Sstevel@tonic-gate * Returns err != SLP_OK only on catastrophic error.
530*7c478bd9Sstevel@tonic-gate */
make_tbs(const char * spi,struct iovec * iov,int iovlen,unsigned int timestamp,unsigned char ** buf,size_t * buflen)531*7c478bd9Sstevel@tonic-gate static SLPError make_tbs(const char *spi,
532*7c478bd9Sstevel@tonic-gate struct iovec *iov,
533*7c478bd9Sstevel@tonic-gate int iovlen,
534*7c478bd9Sstevel@tonic-gate unsigned int timestamp,
535*7c478bd9Sstevel@tonic-gate unsigned char **buf,
536*7c478bd9Sstevel@tonic-gate size_t *buflen) {
537*7c478bd9Sstevel@tonic-gate int i;
538*7c478bd9Sstevel@tonic-gate caddr_t p;
539*7c478bd9Sstevel@tonic-gate size_t off;
540*7c478bd9Sstevel@tonic-gate SLPError err;
541*7c478bd9Sstevel@tonic-gate
542*7c478bd9Sstevel@tonic-gate *buflen = 2 + strlen(spi);
543*7c478bd9Sstevel@tonic-gate
544*7c478bd9Sstevel@tonic-gate for (i = 0; i < iovlen; i++) {
545*7c478bd9Sstevel@tonic-gate *buflen += iov[i].iov_len;
546*7c478bd9Sstevel@tonic-gate }
547*7c478bd9Sstevel@tonic-gate
548*7c478bd9Sstevel@tonic-gate *buflen += sizeof (timestamp);
549*7c478bd9Sstevel@tonic-gate
550*7c478bd9Sstevel@tonic-gate if (!(*buf = malloc(*buflen))) {
551*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "slp_sign", "out of memory");
552*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate
555*7c478bd9Sstevel@tonic-gate /* @@@ ok to use caddr_t? */
556*7c478bd9Sstevel@tonic-gate p = (caddr_t)*buf;
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate /* Lay in SPI string */
559*7c478bd9Sstevel@tonic-gate off = 0;
560*7c478bd9Sstevel@tonic-gate if ((err = slp_add_string(p, *buflen, spi, &off)) != SLP_OK) {
561*7c478bd9Sstevel@tonic-gate return (err);
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate
564*7c478bd9Sstevel@tonic-gate p += off;
565*7c478bd9Sstevel@tonic-gate
566*7c478bd9Sstevel@tonic-gate /* Copy in elements of iov */
567*7c478bd9Sstevel@tonic-gate for (i = 0; i < iovlen; i++) {
568*7c478bd9Sstevel@tonic-gate (void) memcpy(p, iov[i].iov_base, iov[i].iov_len);
569*7c478bd9Sstevel@tonic-gate p += iov[i].iov_len;
570*7c478bd9Sstevel@tonic-gate off += iov[i].iov_len;
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate
573*7c478bd9Sstevel@tonic-gate /* Lay in timestamp */
574*7c478bd9Sstevel@tonic-gate return (slp_add_int32((char *)*buf, *buflen, timestamp, &off));
575*7c478bd9Sstevel@tonic-gate }
576*7c478bd9Sstevel@tonic-gate
577*7c478bd9Sstevel@tonic-gate /*
578*7c478bd9Sstevel@tonic-gate * Creates an auth block from the given parameters:
579*7c478bd9Sstevel@tonic-gate *
580*7c478bd9Sstevel@tonic-gate * sig_in IN Data to be signed
581*7c478bd9Sstevel@tonic-gate * sig_in_len IN Length of sig_in
582*7c478bd9Sstevel@tonic-gate * alias IN signing alias for this auth block
583*7c478bd9Sstevel@tonic-gate * timestamp IN Timestamp for this auth block
584*7c478bd9Sstevel@tonic-gate * abs IN/OUT Buffer of accumulated auth blocks
585*7c478bd9Sstevel@tonic-gate * abs_len IN/OUT Length of abs
586*7c478bd9Sstevel@tonic-gate *
587*7c478bd9Sstevel@tonic-gate * For each new auth block, abs is resized as necessary, and the
588*7c478bd9Sstevel@tonic-gate * new auth block is appended. abs_len is updated accordingly.
589*7c478bd9Sstevel@tonic-gate *
590*7c478bd9Sstevel@tonic-gate * Returns SLP_OK if the signing and auth block creation succeeded.
591*7c478bd9Sstevel@tonic-gate */
make_authblock(struct iovec * authiov,int authiov_len,const char * alias,time_t timestamp,caddr_t * abs,size_t * abs_len)592*7c478bd9Sstevel@tonic-gate static SLPError make_authblock(struct iovec *authiov, int authiov_len,
593*7c478bd9Sstevel@tonic-gate const char *alias, time_t timestamp,
594*7c478bd9Sstevel@tonic-gate caddr_t *abs, size_t *abs_len) {
595*7c478bd9Sstevel@tonic-gate
596*7c478bd9Sstevel@tonic-gate unsigned char *sig_out = NULL;
597*7c478bd9Sstevel@tonic-gate size_t sig_out_len = 0;
598*7c478bd9Sstevel@tonic-gate ami_handle_t *amih = NULL;
599*7c478bd9Sstevel@tonic-gate AMI_STATUS ami_err;
600*7c478bd9Sstevel@tonic-gate size_t off = 0;
601*7c478bd9Sstevel@tonic-gate SLPError err = SLP_OK;
602*7c478bd9Sstevel@tonic-gate caddr_t ab;
603*7c478bd9Sstevel@tonic-gate size_t ab_len;
604*7c478bd9Sstevel@tonic-gate unsigned short bsd;
605*7c478bd9Sstevel@tonic-gate ami_algid *aid;
606*7c478bd9Sstevel@tonic-gate char *dn = NULL;
607*7c478bd9Sstevel@tonic-gate unsigned char *sig_in = NULL;
608*7c478bd9Sstevel@tonic-gate size_t sig_in_len;
609*7c478bd9Sstevel@tonic-gate
610*7c478bd9Sstevel@tonic-gate /* Create the signature */
611*7c478bd9Sstevel@tonic-gate if ((ami_err = dld_ami_init(&amih, alias, NULL, 0, 0, NULL))
612*7c478bd9Sstevel@tonic-gate != AMI_OK) {
613*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "make_authblock", "ami_init failed: %s",
614*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, ami_err));
615*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
616*7c478bd9Sstevel@tonic-gate }
617*7c478bd9Sstevel@tonic-gate
618*7c478bd9Sstevel@tonic-gate /* determine our DN, to be used as the SPI */
619*7c478bd9Sstevel@tonic-gate if (!(dn = alias2dn(amih))) {
620*7c478bd9Sstevel@tonic-gate err = SLP_AUTHENTICATION_FAILED;
621*7c478bd9Sstevel@tonic-gate goto done;
622*7c478bd9Sstevel@tonic-gate }
623*7c478bd9Sstevel@tonic-gate
624*7c478bd9Sstevel@tonic-gate /* make bytes to-be-signed */
625*7c478bd9Sstevel@tonic-gate err = make_tbs(
626*7c478bd9Sstevel@tonic-gate dn, authiov, authiov_len, timestamp, &sig_in, &sig_in_len);
627*7c478bd9Sstevel@tonic-gate if (err != SLP_OK) {
628*7c478bd9Sstevel@tonic-gate goto done;
629*7c478bd9Sstevel@tonic-gate }
630*7c478bd9Sstevel@tonic-gate
631*7c478bd9Sstevel@tonic-gate /* @@@ determine the AID and BSD for this alias */
632*7c478bd9Sstevel@tonic-gate bsd = 1;
633*7c478bd9Sstevel@tonic-gate aid = *ami_rsa_aid;
634*7c478bd9Sstevel@tonic-gate
635*7c478bd9Sstevel@tonic-gate if ((ami_err = dld_ami_sign(amih, sig_in, sig_in_len, AMI_END_DATA,
636*7c478bd9Sstevel@tonic-gate NULL, NULL, 0, aid, &sig_out, &sig_out_len))
637*7c478bd9Sstevel@tonic-gate != AMI_OK) {
638*7c478bd9Sstevel@tonic-gate
639*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "make_authblock", "ami_sign failed: %s",
640*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, ami_err));
641*7c478bd9Sstevel@tonic-gate err = SLP_AUTHENTICATION_FAILED;
642*7c478bd9Sstevel@tonic-gate goto done;
643*7c478bd9Sstevel@tonic-gate }
644*7c478bd9Sstevel@tonic-gate
645*7c478bd9Sstevel@tonic-gate /* We can now calculate the length of the auth block */
646*7c478bd9Sstevel@tonic-gate ab_len =
647*7c478bd9Sstevel@tonic-gate 2 + /* BSD */
648*7c478bd9Sstevel@tonic-gate 2 + /* length */
649*7c478bd9Sstevel@tonic-gate 4 + /* timestamp */
650*7c478bd9Sstevel@tonic-gate 2 + strlen(dn) + /* SPI string */
651*7c478bd9Sstevel@tonic-gate sig_out_len; /* the signature */
652*7c478bd9Sstevel@tonic-gate
653*7c478bd9Sstevel@tonic-gate /* Grow buffer for already-created auth blocks, if necessary */
654*7c478bd9Sstevel@tonic-gate if (*abs_len != 0) {
655*7c478bd9Sstevel@tonic-gate if (!(*abs = realloc(*abs, *abs_len + ab_len))) {
656*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "make_authblock", "out of memory");
657*7c478bd9Sstevel@tonic-gate err = SLP_MEMORY_ALLOC_FAILED;
658*7c478bd9Sstevel@tonic-gate goto done;
659*7c478bd9Sstevel@tonic-gate }
660*7c478bd9Sstevel@tonic-gate }
661*7c478bd9Sstevel@tonic-gate ab = *abs + *abs_len;
662*7c478bd9Sstevel@tonic-gate *abs_len += ab_len;
663*7c478bd9Sstevel@tonic-gate
664*7c478bd9Sstevel@tonic-gate /* BSD */
665*7c478bd9Sstevel@tonic-gate err = slp_add_sht(ab, ab_len, bsd, &off);
666*7c478bd9Sstevel@tonic-gate
667*7c478bd9Sstevel@tonic-gate /* Auth block length */
668*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
669*7c478bd9Sstevel@tonic-gate err = slp_add_sht(ab, ab_len, ab_len, &off);
670*7c478bd9Sstevel@tonic-gate }
671*7c478bd9Sstevel@tonic-gate
672*7c478bd9Sstevel@tonic-gate /* timestamp */
673*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
674*7c478bd9Sstevel@tonic-gate err = slp_add_int32(ab, ab_len, timestamp, &off);
675*7c478bd9Sstevel@tonic-gate }
676*7c478bd9Sstevel@tonic-gate
677*7c478bd9Sstevel@tonic-gate /* SPI string */
678*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
679*7c478bd9Sstevel@tonic-gate err = slp_add_string(ab, ab_len, dn, &off);
680*7c478bd9Sstevel@tonic-gate }
681*7c478bd9Sstevel@tonic-gate
682*7c478bd9Sstevel@tonic-gate /* Signature */
683*7c478bd9Sstevel@tonic-gate if (err == SLP_OK) {
684*7c478bd9Sstevel@tonic-gate (void) memcpy(ab + off, sig_out, sig_out_len);
685*7c478bd9Sstevel@tonic-gate }
686*7c478bd9Sstevel@tonic-gate
687*7c478bd9Sstevel@tonic-gate done:
688*7c478bd9Sstevel@tonic-gate if (amih) {
689*7c478bd9Sstevel@tonic-gate dld_ami_end(amih);
690*7c478bd9Sstevel@tonic-gate }
691*7c478bd9Sstevel@tonic-gate if (dn) free(dn);
692*7c478bd9Sstevel@tonic-gate
693*7c478bd9Sstevel@tonic-gate if (sig_in) free(sig_in);
694*7c478bd9Sstevel@tonic-gate if (sig_out) free(sig_out);
695*7c478bd9Sstevel@tonic-gate
696*7c478bd9Sstevel@tonic-gate if (err == SLP_MEMORY_ALLOC_FAILED) {
697*7c478bd9Sstevel@tonic-gate /* critical error; abort */
698*7c478bd9Sstevel@tonic-gate free(*abs);
699*7c478bd9Sstevel@tonic-gate }
700*7c478bd9Sstevel@tonic-gate
701*7c478bd9Sstevel@tonic-gate return (err);
702*7c478bd9Sstevel@tonic-gate }
703*7c478bd9Sstevel@tonic-gate
704*7c478bd9Sstevel@tonic-gate /*
705*7c478bd9Sstevel@tonic-gate * The actual verification routine which interacts with the security
706*7c478bd9Sstevel@tonic-gate * backend to get a certificate for the given SPI and use that cert
707*7c478bd9Sstevel@tonic-gate * to verify the signature contained in the auth block.
708*7c478bd9Sstevel@tonic-gate *
709*7c478bd9Sstevel@tonic-gate * inbytes IN bytes to be verified
710*7c478bd9Sstevel@tonic-gate * inbytes_len IN length of inbytes
711*7c478bd9Sstevel@tonic-gate * bsd IN BSD for this signature
712*7c478bd9Sstevel@tonic-gate * sig IN the signature
713*7c478bd9Sstevel@tonic-gate * siglen IN length of sig
714*7c478bd9Sstevel@tonic-gate * spi IN SPI for this signature, not escaped
715*7c478bd9Sstevel@tonic-gate *
716*7c478bd9Sstevel@tonic-gate * Returns SLP_OK if the signature is verified, or SLP_AUTHENTICATION_FAILED
717*7c478bd9Sstevel@tonic-gate * if any error occured.
718*7c478bd9Sstevel@tonic-gate */
do_verify(unsigned char * inbytes,size_t inbytes_len,unsigned short bsd,const unsigned char * sig,size_t siglen,const char * esc_spi)719*7c478bd9Sstevel@tonic-gate static SLPError do_verify(unsigned char *inbytes, size_t inbytes_len,
720*7c478bd9Sstevel@tonic-gate unsigned short bsd, const unsigned char *sig,
721*7c478bd9Sstevel@tonic-gate size_t siglen, const char *esc_spi) {
722*7c478bd9Sstevel@tonic-gate
723*7c478bd9Sstevel@tonic-gate AMI_STATUS ami_err;
724*7c478bd9Sstevel@tonic-gate ami_handle_t *amih = NULL;
725*7c478bd9Sstevel@tonic-gate SLPError err;
726*7c478bd9Sstevel@tonic-gate ami_cert *certs = NULL;
727*7c478bd9Sstevel@tonic-gate int icert, ccnt;
728*7c478bd9Sstevel@tonic-gate ami_algid *aid;
729*7c478bd9Sstevel@tonic-gate char *spi = NULL;
730*7c478bd9Sstevel@tonic-gate
731*7c478bd9Sstevel@tonic-gate /* Get the right AID */
732*7c478bd9Sstevel@tonic-gate switch (bsd) {
733*7c478bd9Sstevel@tonic-gate case 1:
734*7c478bd9Sstevel@tonic-gate aid = *ami_rsa_aid;
735*7c478bd9Sstevel@tonic-gate break;
736*7c478bd9Sstevel@tonic-gate case 2:
737*7c478bd9Sstevel@tonic-gate aid = *ami_dsa_aid;
738*7c478bd9Sstevel@tonic-gate break;
739*7c478bd9Sstevel@tonic-gate default:
740*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "do_verify",
741*7c478bd9Sstevel@tonic-gate "Unsupported BSD %d for given SPI %s", bsd, spi);
742*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
743*7c478bd9Sstevel@tonic-gate }
744*7c478bd9Sstevel@tonic-gate
745*7c478bd9Sstevel@tonic-gate if ((ami_err = dld_ami_init(&amih, spi, NULL, 0, 0, NULL)) != AMI_OK) {
746*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "do_verify", "ami_init failed: %s",
747*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, ami_err));
748*7c478bd9Sstevel@tonic-gate return (SLP_AUTHENTICATION_FAILED);
749*7c478bd9Sstevel@tonic-gate }
750*7c478bd9Sstevel@tonic-gate
751*7c478bd9Sstevel@tonic-gate /* unescape SPI */
752*7c478bd9Sstevel@tonic-gate if ((err = SLPUnescape(esc_spi, &spi, SLP_FALSE))) {
753*7c478bd9Sstevel@tonic-gate goto done;
754*7c478bd9Sstevel@tonic-gate }
755*7c478bd9Sstevel@tonic-gate
756*7c478bd9Sstevel@tonic-gate /* get certificate */
757*7c478bd9Sstevel@tonic-gate if ((ami_err = dld_ami_get_cert(amih, spi, &certs, &ccnt)) != AMI_OK) {
758*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "do_verify",
759*7c478bd9Sstevel@tonic-gate "Can not get certificate for %s: %s",
760*7c478bd9Sstevel@tonic-gate spi, dld_ami_strerror(amih, ami_err));
761*7c478bd9Sstevel@tonic-gate err = SLP_AUTHENTICATION_FAILED;
762*7c478bd9Sstevel@tonic-gate goto done;
763*7c478bd9Sstevel@tonic-gate }
764*7c478bd9Sstevel@tonic-gate
765*7c478bd9Sstevel@tonic-gate /* @@@ select the right cert, if more than one */
766*7c478bd9Sstevel@tonic-gate icert = 0;
767*7c478bd9Sstevel@tonic-gate
768*7c478bd9Sstevel@tonic-gate if ((ami_err = dld_ami_verify(amih, inbytes, inbytes_len, AMI_END_DATA,
769*7c478bd9Sstevel@tonic-gate certs[icert].info.pubKeyInfo->algorithm,
770*7c478bd9Sstevel@tonic-gate certs[icert].info.pubKeyInfo->pubKey.value,
771*7c478bd9Sstevel@tonic-gate certs[icert].info.pubKeyInfo->pubKey.length,
772*7c478bd9Sstevel@tonic-gate aid, sig, siglen)) != AMI_OK) {
773*7c478bd9Sstevel@tonic-gate
774*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "do_verify", "ami_verify failed: %s",
775*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, ami_err));
776*7c478bd9Sstevel@tonic-gate err = SLP_AUTHENTICATION_FAILED;
777*7c478bd9Sstevel@tonic-gate goto done;
778*7c478bd9Sstevel@tonic-gate }
779*7c478bd9Sstevel@tonic-gate
780*7c478bd9Sstevel@tonic-gate err = check_spis(amih, certs, icert, spi);
781*7c478bd9Sstevel@tonic-gate
782*7c478bd9Sstevel@tonic-gate done:
783*7c478bd9Sstevel@tonic-gate if (certs) {
784*7c478bd9Sstevel@tonic-gate dld_ami_free_cert_list(&certs, ccnt);
785*7c478bd9Sstevel@tonic-gate }
786*7c478bd9Sstevel@tonic-gate
787*7c478bd9Sstevel@tonic-gate if (amih) {
788*7c478bd9Sstevel@tonic-gate dld_ami_end(amih);
789*7c478bd9Sstevel@tonic-gate }
790*7c478bd9Sstevel@tonic-gate
791*7c478bd9Sstevel@tonic-gate if (spi) free(spi);
792*7c478bd9Sstevel@tonic-gate
793*7c478bd9Sstevel@tonic-gate return (err);
794*7c478bd9Sstevel@tonic-gate }
795*7c478bd9Sstevel@tonic-gate
796*7c478bd9Sstevel@tonic-gate /*
797*7c478bd9Sstevel@tonic-gate * Gets this process' DN, or returns NULL on failure. Caller must free
798*7c478bd9Sstevel@tonic-gate * the result. The reslting DN will be escaped.
799*7c478bd9Sstevel@tonic-gate */
alias2dn(ami_handle_t * amih)800*7c478bd9Sstevel@tonic-gate static char *alias2dn(ami_handle_t *amih) {
801*7c478bd9Sstevel@tonic-gate ami_cert *certs;
802*7c478bd9Sstevel@tonic-gate int ccnt;
803*7c478bd9Sstevel@tonic-gate AMI_STATUS status;
804*7c478bd9Sstevel@tonic-gate char *answer = NULL;
805*7c478bd9Sstevel@tonic-gate char *esc_answer;
806*7c478bd9Sstevel@tonic-gate
807*7c478bd9Sstevel@tonic-gate if ((status = dld_ami_get_cert(amih, NULL, &certs, &ccnt)) != AMI_OK) {
808*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "alias2dn",
809*7c478bd9Sstevel@tonic-gate "Can not get my DN: %s",
810*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, status));
811*7c478bd9Sstevel@tonic-gate return (NULL);
812*7c478bd9Sstevel@tonic-gate }
813*7c478bd9Sstevel@tonic-gate
814*7c478bd9Sstevel@tonic-gate if (ccnt == 0) {
815*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "alias2dn",
816*7c478bd9Sstevel@tonic-gate "No cert found for myself");
817*7c478bd9Sstevel@tonic-gate return (NULL);
818*7c478bd9Sstevel@tonic-gate }
819*7c478bd9Sstevel@tonic-gate
820*7c478bd9Sstevel@tonic-gate if ((status = dld_ami_dn2str(amih, certs[0].info.subject, &answer))
821*7c478bd9Sstevel@tonic-gate != AMI_OK) {
822*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "alias2dn",
823*7c478bd9Sstevel@tonic-gate "Can not convert DN to string: %s",
824*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, status));
825*7c478bd9Sstevel@tonic-gate answer = NULL;
826*7c478bd9Sstevel@tonic-gate goto done;
827*7c478bd9Sstevel@tonic-gate }
828*7c478bd9Sstevel@tonic-gate
829*7c478bd9Sstevel@tonic-gate if (SLPEscape(answer, &esc_answer, SLP_FALSE) != SLP_OK) {
830*7c478bd9Sstevel@tonic-gate free(answer);
831*7c478bd9Sstevel@tonic-gate answer = NULL;
832*7c478bd9Sstevel@tonic-gate } else {
833*7c478bd9Sstevel@tonic-gate free(answer);
834*7c478bd9Sstevel@tonic-gate answer = esc_answer;
835*7c478bd9Sstevel@tonic-gate }
836*7c478bd9Sstevel@tonic-gate
837*7c478bd9Sstevel@tonic-gate done:
838*7c478bd9Sstevel@tonic-gate dld_ami_free_cert_list(&certs, ccnt);
839*7c478bd9Sstevel@tonic-gate
840*7c478bd9Sstevel@tonic-gate return (answer);
841*7c478bd9Sstevel@tonic-gate }
842*7c478bd9Sstevel@tonic-gate
check_spis(ami_handle_t * amih,ami_cert * certs,int icert,const char * spi)843*7c478bd9Sstevel@tonic-gate static SLPError check_spis(ami_handle_t *amih,
844*7c478bd9Sstevel@tonic-gate ami_cert *certs,
845*7c478bd9Sstevel@tonic-gate int icert,
846*7c478bd9Sstevel@tonic-gate const char *spi) {
847*7c478bd9Sstevel@tonic-gate ami_cert *chain = NULL;
848*7c478bd9Sstevel@tonic-gate int ccnt;
849*7c478bd9Sstevel@tonic-gate const char *cas[2];
850*7c478bd9Sstevel@tonic-gate char *prop_spi;
851*7c478bd9Sstevel@tonic-gate char *ue_spi;
852*7c478bd9Sstevel@tonic-gate char *p;
853*7c478bd9Sstevel@tonic-gate SLPError err;
854*7c478bd9Sstevel@tonic-gate AMI_STATUS ami_err;
855*7c478bd9Sstevel@tonic-gate
856*7c478bd9Sstevel@tonic-gate /* If configured SPI == authblock SPI, we are done */
857*7c478bd9Sstevel@tonic-gate prop_spi = (char *)SLPGetProperty(SLP_CONFIG_SPI);
858*7c478bd9Sstevel@tonic-gate if (!prop_spi || !*prop_spi) {
859*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "do_verify", "no SPI configured");
860*7c478bd9Sstevel@tonic-gate err = SLP_AUTHENTICATION_FAILED;
861*7c478bd9Sstevel@tonic-gate goto done;
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate
864*7c478bd9Sstevel@tonic-gate /* dup it so we can modify it */
865*7c478bd9Sstevel@tonic-gate if (!(prop_spi = strdup(prop_spi))) {
866*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "do_verify", "out of memory");
867*7c478bd9Sstevel@tonic-gate err = SLP_MEMORY_ALLOC_FAILED;
868*7c478bd9Sstevel@tonic-gate goto done;
869*7c478bd9Sstevel@tonic-gate }
870*7c478bd9Sstevel@tonic-gate
871*7c478bd9Sstevel@tonic-gate /* if more than one SPI given, discard all but first */
872*7c478bd9Sstevel@tonic-gate if ((p = slp_utf_strchr(prop_spi, ','))) {
873*7c478bd9Sstevel@tonic-gate *p = 0;
874*7c478bd9Sstevel@tonic-gate }
875*7c478bd9Sstevel@tonic-gate
876*7c478bd9Sstevel@tonic-gate /* unescape configured DNs */
877*7c478bd9Sstevel@tonic-gate if ((err = SLPUnescape(prop_spi, &ue_spi, SLP_FALSE)) != SLP_OK) {
878*7c478bd9Sstevel@tonic-gate goto done;
879*7c478bd9Sstevel@tonic-gate }
880*7c478bd9Sstevel@tonic-gate free(prop_spi);
881*7c478bd9Sstevel@tonic-gate prop_spi = ue_spi;
882*7c478bd9Sstevel@tonic-gate
883*7c478bd9Sstevel@tonic-gate if (dncmp(amih, prop_spi, spi) == 0) {
884*7c478bd9Sstevel@tonic-gate /* they match, so we are done */
885*7c478bd9Sstevel@tonic-gate err = SLP_OK;
886*7c478bd9Sstevel@tonic-gate goto done;
887*7c478bd9Sstevel@tonic-gate }
888*7c478bd9Sstevel@tonic-gate
889*7c478bd9Sstevel@tonic-gate /*
890*7c478bd9Sstevel@tonic-gate * Else we need to traverse the cert chain. ami_get_cert_chain
891*7c478bd9Sstevel@tonic-gate * verifies each link in the chain, so no need to do it again.
892*7c478bd9Sstevel@tonic-gate */
893*7c478bd9Sstevel@tonic-gate cas[0] = prop_spi;
894*7c478bd9Sstevel@tonic-gate cas[1] = NULL;
895*7c478bd9Sstevel@tonic-gate ami_err = dld_ami_get_cert_chain(amih, certs + icert, cas, 0,
896*7c478bd9Sstevel@tonic-gate &chain, &ccnt);
897*7c478bd9Sstevel@tonic-gate if (ami_err != AMI_OK) {
898*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "do_verify",
899*7c478bd9Sstevel@tonic-gate "can not get cert chain: %s",
900*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, ami_err));
901*7c478bd9Sstevel@tonic-gate err = SLP_AUTHENTICATION_FAILED;
902*7c478bd9Sstevel@tonic-gate goto done;
903*7c478bd9Sstevel@tonic-gate }
904*7c478bd9Sstevel@tonic-gate
905*7c478bd9Sstevel@tonic-gate err = SLP_OK;
906*7c478bd9Sstevel@tonic-gate
907*7c478bd9Sstevel@tonic-gate done:
908*7c478bd9Sstevel@tonic-gate if (chain) {
909*7c478bd9Sstevel@tonic-gate dld_ami_free_cert_list(&chain, ccnt);
910*7c478bd9Sstevel@tonic-gate }
911*7c478bd9Sstevel@tonic-gate
912*7c478bd9Sstevel@tonic-gate if (prop_spi) free(prop_spi);
913*7c478bd9Sstevel@tonic-gate
914*7c478bd9Sstevel@tonic-gate return (err);
915*7c478bd9Sstevel@tonic-gate }
916*7c478bd9Sstevel@tonic-gate
dncmp(ami_handle_t * amih,const char * s1,const char * s2)917*7c478bd9Sstevel@tonic-gate static int dncmp(ami_handle_t *amih, const char *s1, const char *s2) {
918*7c478bd9Sstevel@tonic-gate AMI_STATUS status;
919*7c478bd9Sstevel@tonic-gate ami_name *dn1 = NULL;
920*7c478bd9Sstevel@tonic-gate ami_name *dn2 = NULL;
921*7c478bd9Sstevel@tonic-gate char *dnstr1 = NULL;
922*7c478bd9Sstevel@tonic-gate char *dnstr2 = NULL;
923*7c478bd9Sstevel@tonic-gate int answer;
924*7c478bd9Sstevel@tonic-gate
925*7c478bd9Sstevel@tonic-gate /* Normalize: convert to DN structs and back to strings */
926*7c478bd9Sstevel@tonic-gate if ((status = dld_ami_str2dn(amih, (char *)s1, &dn1)) != AMI_OK) {
927*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "dncmp",
928*7c478bd9Sstevel@tonic-gate "can not create DN structure for %s: %s",
929*7c478bd9Sstevel@tonic-gate s1,
930*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, status));
931*7c478bd9Sstevel@tonic-gate answer = 1;
932*7c478bd9Sstevel@tonic-gate goto done;
933*7c478bd9Sstevel@tonic-gate }
934*7c478bd9Sstevel@tonic-gate
935*7c478bd9Sstevel@tonic-gate if ((status = dld_ami_str2dn(amih, (char *)s2, &dn2)) != AMI_OK) {
936*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "dncmp",
937*7c478bd9Sstevel@tonic-gate "can not create DN structure for %s: %s",
938*7c478bd9Sstevel@tonic-gate s2,
939*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, status));
940*7c478bd9Sstevel@tonic-gate answer = 1;
941*7c478bd9Sstevel@tonic-gate goto done;
942*7c478bd9Sstevel@tonic-gate }
943*7c478bd9Sstevel@tonic-gate
944*7c478bd9Sstevel@tonic-gate /* convert back to strings */
945*7c478bd9Sstevel@tonic-gate if ((status = dld_ami_dn2str(amih, dn1, &dnstr1)) != AMI_OK) {
946*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "dncmp",
947*7c478bd9Sstevel@tonic-gate "can not convert DN to string: %s",
948*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, status));
949*7c478bd9Sstevel@tonic-gate answer = 1;
950*7c478bd9Sstevel@tonic-gate goto done;
951*7c478bd9Sstevel@tonic-gate }
952*7c478bd9Sstevel@tonic-gate
953*7c478bd9Sstevel@tonic-gate if ((status = dld_ami_dn2str(amih, dn2, &dnstr2)) != AMI_OK) {
954*7c478bd9Sstevel@tonic-gate slp_err(LOG_INFO, 0, "dncmp",
955*7c478bd9Sstevel@tonic-gate "can not convert DN to string: %s",
956*7c478bd9Sstevel@tonic-gate dld_ami_strerror(amih, status));
957*7c478bd9Sstevel@tonic-gate answer = 1;
958*7c478bd9Sstevel@tonic-gate goto done;
959*7c478bd9Sstevel@tonic-gate }
960*7c478bd9Sstevel@tonic-gate
961*7c478bd9Sstevel@tonic-gate answer = strcasecmp(dnstr1, dnstr2);
962*7c478bd9Sstevel@tonic-gate
963*7c478bd9Sstevel@tonic-gate done:
964*7c478bd9Sstevel@tonic-gate if (dn1) {
965*7c478bd9Sstevel@tonic-gate dld_ami_free_dn(&dn1);
966*7c478bd9Sstevel@tonic-gate }
967*7c478bd9Sstevel@tonic-gate
968*7c478bd9Sstevel@tonic-gate if (dn2) {
969*7c478bd9Sstevel@tonic-gate dld_ami_free_dn(&dn2);
970*7c478bd9Sstevel@tonic-gate }
971*7c478bd9Sstevel@tonic-gate
972*7c478bd9Sstevel@tonic-gate if (dnstr1) free(dnstr1);
973*7c478bd9Sstevel@tonic-gate if (dnstr2) free(dnstr2);
974*7c478bd9Sstevel@tonic-gate
975*7c478bd9Sstevel@tonic-gate return (answer);
976*7c478bd9Sstevel@tonic-gate }
977