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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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