1/*
2 * NSS utility functions
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8#include <stdio.h>
9#include <string.h>
10#include "prerror.h"
11#include "secitem.h"
12#include "prnetdb.h"
13#include "cert.h"
14#include "nspr.h"
15#include "secder.h"
16#include "key.h"
17#include "nss.h"
18#include "ssl.h"
19#include "pk11func.h"	/* for PK11_ function calls */
20
21/*
22 * This callback used by SSL to pull client sertificate upon
23 * server request
24 */
25SECStatus
26NSS_GetClientAuthData(void *                       arg,
27                      PRFileDesc *                 socket,
28		      struct CERTDistNamesStr *    caNames,
29		      struct CERTCertificateStr ** pRetCert,
30		      struct SECKEYPrivateKeyStr **pRetKey)
31{
32  CERTCertificate *  cert = NULL;
33  SECKEYPrivateKey * privkey = NULL;
34  char *             chosenNickName = (char *)arg;    /* CONST */
35  void *             proto_win  = NULL;
36  SECStatus          rv         = SECFailure;
37
38  proto_win = SSL_RevealPinArg(socket);
39
40  if (chosenNickName) {
41    cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
42                                    chosenNickName, certUsageSSLClient,
43                                    PR_FALSE, proto_win);
44    if ( cert ) {
45      privkey = PK11_FindKeyByAnyCert(cert, proto_win);
46      if ( privkey ) {
47	rv = SECSuccess;
48      } else {
49	CERT_DestroyCertificate(cert);
50      }
51    }
52  } else { /* no name given, automatically find the right cert. */
53    CERTCertNicknames * names;
54    int                 i;
55
56    names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
57				  SEC_CERT_NICKNAMES_USER, proto_win);
58    if (names != NULL) {
59      for (i = 0; i < names->numnicknames; i++) {
60	cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
61                            names->nicknames[i], certUsageSSLClient,
62                            PR_FALSE, proto_win);
63	if ( !cert )
64	  continue;
65	/* Only check unexpired certs */
66	if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) !=
67	    secCertTimeValid ) {
68	  CERT_DestroyCertificate(cert);
69	  continue;
70	}
71	rv = NSS_CmpCertChainWCANames(cert, caNames);
72	if ( rv == SECSuccess ) {
73	  privkey = PK11_FindKeyByAnyCert(cert, proto_win);
74	  if ( privkey )
75	    break;
76	}
77	rv = SECFailure;
78	CERT_DestroyCertificate(cert);
79      }
80      CERT_FreeNicknames(names);
81    }
82  }
83  if (rv == SECSuccess) {
84    *pRetCert = cert;
85    *pRetKey  = privkey;
86  }
87  return rv;
88}
89
90