sample.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:9k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* 
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "cmtcmn.h"
  35. #include "cmtjs.h"
  36. #include "appsock.h"
  37. #include <stdarg.h>
  38. #include <string.h>
  39. #ifdef XP_UNIX
  40. #include <netdb.h>
  41. #include <sys/types.h>
  42. #include <sys/socket.h>
  43. #include <netinet/in.h>
  44. #include <arpa/inet.h>
  45. #endif
  46. #ifdef WIN32
  47. #include <direct.h>
  48. #endif
  49. /*
  50.  * This is a simple program that tries to detect if the psm server is loaded.
  51.  * If the server is not loaded, it will start it.  The program will then 
  52.  * connect to the server and fetch an HTML page from an SSL server.
  53.  *
  54.  * NOTE: This sample program does not implement a mutex for the libraries.
  55.  * If implementing a threaded application, then pass in a mutex structure
  56.  * so that connections to the psm server happen in a thread safe manner.
  57.  */
  58. #define NUM_CONNECT_TRIES 10
  59. #define READ_BUFFER_SIZE  1024
  60. void
  61. usage(void)
  62. {
  63.     printf("Usage:n"
  64.            "tcmtsample <secure site>nn"
  65.            "This program will then echo the retrieved HTML to the screenn");
  66. }
  67. void
  68. errorMessage(int err,char *msg, ...)
  69. {
  70.     va_list args;
  71.     
  72.     va_start(args, msg);
  73.     fprintf (stderr, "cmtSample%s: ", (err) ? " error" : "");
  74.     vfprintf (stderr, msg, args);
  75.     fprintf (stderr, "n");
  76.     va_end(args);
  77.     if (err) {
  78.         exit (err);
  79.     }
  80. }
  81. #ifdef XP_UNIX
  82. #define FILE_PATH_SEPARATOR '/'
  83. #elif defined (WIN32)
  84. #define FILE_PATH_SEPARATOR '\'
  85. #else
  86. #error Tell me what the file path separator is.
  87. #endif
  88. PCMT_CONTROL
  89. connect_to_psm(void)
  90. {
  91.     PCMT_CONTROL control=NULL;
  92.     char path[256], *tmp;
  93. #ifdef XP_UNIX
  94.     if (getcwd(path,256) == NULL) {
  95.       return NULL;
  96.     }
  97. #elif defined(WIN32)
  98.     if (_getcwd(path,256) == NULL) {
  99.       return NULL;
  100.     }
  101. #else
  102. #error Teach me how to get the current working directory.
  103. #endif
  104.     tmp = &path[strlen(path)];
  105.     sprintf(tmp,"%c%s", FILE_PATH_SEPARATOR, "psm");
  106.     return CMT_EstablishControlConnection(path, &socketFuncs, NULL);
  107. }
  108. #define HTTPS_STRING "https://"
  109. char*
  110. extract_host_from_url(char *url)
  111. {
  112.     char *start, *end, *retString=NULL;
  113.     while(isspace(*url)) {
  114.         url++;
  115.     }
  116.     url = strdup(url);
  117.     start = strstr(url, HTTPS_STRING);
  118.     if (start == NULL) {
  119.         return NULL;
  120.     }
  121.     start += strlen(HTTPS_STRING);
  122.     /*
  123.      * Figure out the end of the host name.
  124.      */
  125.     end = strchr(start, ':');
  126.     if (end != NULL) {
  127.         *end = '';
  128.     } else {
  129.         end = strchr(start, '/');
  130.         if (end != NULL) {
  131.             *end = '';
  132.         } else {
  133.             end = strchr(start, ' ');
  134.             if (end != NULL) {
  135.                 *end = '';
  136.             }
  137.         }
  138.     }
  139.     retString = strdup(start);
  140.     return retString;
  141. }
  142. CMUint32
  143. get_port_from_url(char *url)
  144. {
  145.     char *colon, *port;
  146.     url = strdup(url);
  147.     colon = strrchr(url, ':');
  148.     if (colon == NULL ||
  149.         !isdigit(colon[1])) {
  150.         /* Return the default SSL port. */
  151.         free(url);
  152.         return 443;
  153.     }
  154.     colon++;
  155.     port = colon;
  156.     while(isdigit(*colon))
  157.         colon++;
  158.     colon[1] = '';
  159.     free(url);
  160.     return (CMUint32)atol(port);
  161. }
  162. char*
  163. extract_get_target(char *url)
  164. {
  165.     char *slash;
  166.     slash = strstr(url, "//");
  167.     slash += 2;
  168.     slash = strchr(slash, '/');
  169.     if (slash != NULL)
  170.         return strdup (slash);
  171.     else 
  172.         return strdup ("/");
  173. }
  174. /*
  175.  * We'll use this function for prompting for a password.
  176.  */
  177. char*
  178. passwordCallback(void *arg, char *prompt, void *cotext, int isPaswd)
  179. {
  180.     char input[256];
  181.     
  182.     printf(prompt);
  183.     fgets(input, 256, stdin);
  184.     return strdup(input);
  185. }
  186. void
  187. freeCallback(char *userInput)
  188. {
  189.   free (userInput);
  190. }
  191. #define NUM_PREFS 2
  192. int 
  193. main(int argc, char **argv)
  194. {
  195.   PCMT_CONTROL control;
  196.     CMTSocket sock, selSock;
  197.     char *hostname;
  198.     struct hostent *host;
  199.     char *ipAddress;
  200.     char buffer[READ_BUFFER_SIZE];
  201.     size_t bytesRead;
  202.     struct sockaddr_in destAddr;
  203.     char *getString;
  204.     char requestString[256];
  205.     char *profile;
  206.     CMTSetPrefElement prefs[NUM_PREFS];
  207.     char profileDir[256];
  208. #ifdef WIN32
  209.     WORD WSAVersion = 0x0101;
  210.     WSADATA WSAData;
  211.     WSAStartup (WSAVersion, &WSAData);
  212. #endif
  213.     if (argc < 2) {
  214.         usage();
  215.         return 1;
  216.     }
  217.     errorMessage (0,"cmtsample v1.0");
  218.     errorMessage (0,"Will try connecting to site %s", argv[1]);
  219.     if (strstr(argv[1], "https://") == NULL) {
  220.         errorMessage(2,"%s is not a secure site", argv[1]);
  221.     }
  222.     control = connect_to_psm();
  223.     if (control == NULL) {
  224.         errorMessage(3, "Could not connect to the psm server");
  225.     }
  226.     /* 
  227.      * Now we have to send the hello message.
  228.      */
  229. #ifdef WIN32
  230.     profile = strdup("default");
  231.     sprintf(profileDir,"%s", "c:\default");
  232. #elif defined (XP_UNIX)
  233.     profile = getenv("LOGNAME");
  234.     sprintf(profileDir, "%s/.netscape", getenv("HOME"));
  235. #else
  236. #error Teach me how to fill in the user profile.
  237. #endif
  238.     if (CMT_Hello(control, PROTOCOL_VERSION,
  239.   profile, profileDir) != CMTSuccess)
  240.     {
  241.         errorMessage(10, "Failed to send the Hello Message.");
  242.     }
  243.     CMT_SetPromptCallback(control, passwordCallback, NULL);
  244.     CMT_SetAppFreeCallback(control, freeCallback);
  245.     /*
  246.      * Now pass along some preferences to psm.  We'll pass hard coded
  247.      * ones here, but apps should figure out a way to manage their user's
  248.      * preferences.
  249.      */
  250.     prefs[0].key   = "security.enable_ssl2";
  251.     prefs[0].value = "true";
  252.     prefs[0].type  = CMT_PREF_BOOL;
  253.     prefs[1].key   = "security.enable_ssl3";
  254.     prefs[1].value = "true";
  255.     prefs[1].type  = CMT_PREF_BOOL;
  256.     CMT_PassAllPrefs(control, NUM_PREFS, prefs);
  257.     hostname = extract_host_from_url(argv[1]);
  258.     host = gethostbyname(hostname);
  259.     if (host == NULL) {
  260.         errorMessage(11, "gethostbyname for %s failed", hostname);
  261.     }
  262.     if (host->h_length != 4) {
  263.         errorMessage(4, "Site %s uses IV v6 socket.  Not supported by psm.");
  264.     }
  265.     
  266.     /* Create the socket we will use to get the decrypted data back from
  267.      * the psm server.
  268.      */
  269.     sock = APP_GetSocket(0);
  270.     if (sock == NULL) {
  271.         errorMessage(5, "Could not create new socket for communication with "
  272.                         "the psm server.");
  273.     }
  274.     memcpy(&(destAddr.sin_addr.s_addr), host->h_addr, host->h_length);
  275.     ipAddress = inet_ntoa(destAddr.sin_addr);
  276.     errorMessage(0, "Mapped %s to the following IP address: %s", argv[1],
  277.                  ipAddress);
  278.     if (CMT_OpenSSLConnection(control, sock, SSM_REQUEST_SSL_DATA_SSL,
  279.                               get_port_from_url(argv[1]), ipAddress, 
  280.                               hostname, CM_FALSE, NULL) != CMTSuccess) {
  281.         errorMessage(6, "Could not open SSL connection to %s.", argv[1]);
  282.     }
  283.     getString = extract_get_target(argv[1]);
  284.     sprintf(requestString, 
  285.             "GET %s HTTP/1.0rn"
  286.             "rn", getString, hostname);
  287.     APP_Send(sock, requestString, strlen(requestString));
  288.     /*
  289.      * Now all we have to do is sit here and fetch the data from the
  290.      * socket.
  291.      */
  292.     errorMessage (0, "About to print out the fetched page.");
  293.     while ((selSock=APP_Select(&sock, 1, 0)) != NULL) {
  294.         if (selSock == sock) {
  295.             bytesRead = APP_Receive(sock, buffer, READ_BUFFER_SIZE-1);
  296.             if (bytesRead == -1 || bytesRead == 0) {
  297.                 break;
  298.             }
  299.             buffer[bytesRead] = '';
  300.             fprintf(stderr, buffer);
  301.         }
  302.     }
  303.     fprintf(stderr,"n");
  304.     if (bytesRead == -1) {
  305.         errorMessage(7, "Error receiving decrypted data from psm.");
  306.     }
  307.     errorMessage(0, "Successfully read the entire page.");
  308.     if (CMT_DestroyDataConnection(control, sock) != CMTSuccess) {
  309.         errorMessage(8, "Error destroygin the SSL data connection "
  310.                      "with the psm server.");
  311.     }
  312.     if (CMT_CloseControlConnection(control) != CMTSuccess) {
  313.         errorMessage(9, "Error closing the control connection.");
  314.     }
  315.     return 0;
  316. }