sample.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:9k
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #include "cmtcmn.h"
- #include "cmtjs.h"
- #include "appsock.h"
- #include <stdarg.h>
- #include <string.h>
- #ifdef XP_UNIX
- #include <netdb.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #endif
- #ifdef WIN32
- #include <direct.h>
- #endif
- /*
- * This is a simple program that tries to detect if the psm server is loaded.
- * If the server is not loaded, it will start it. The program will then
- * connect to the server and fetch an HTML page from an SSL server.
- *
- * NOTE: This sample program does not implement a mutex for the libraries.
- * If implementing a threaded application, then pass in a mutex structure
- * so that connections to the psm server happen in a thread safe manner.
- */
- #define NUM_CONNECT_TRIES 10
- #define READ_BUFFER_SIZE 1024
- void
- usage(void)
- {
- printf("Usage:n"
- "tcmtsample <secure site>nn"
- "This program will then echo the retrieved HTML to the screenn");
- }
- void
- errorMessage(int err,char *msg, ...)
- {
- va_list args;
-
- va_start(args, msg);
- fprintf (stderr, "cmtSample%s: ", (err) ? " error" : "");
- vfprintf (stderr, msg, args);
- fprintf (stderr, "n");
- va_end(args);
- if (err) {
- exit (err);
- }
- }
- #ifdef XP_UNIX
- #define FILE_PATH_SEPARATOR '/'
- #elif defined (WIN32)
- #define FILE_PATH_SEPARATOR '\'
- #else
- #error Tell me what the file path separator is.
- #endif
- PCMT_CONTROL
- connect_to_psm(void)
- {
- PCMT_CONTROL control=NULL;
- char path[256], *tmp;
- #ifdef XP_UNIX
- if (getcwd(path,256) == NULL) {
- return NULL;
- }
- #elif defined(WIN32)
- if (_getcwd(path,256) == NULL) {
- return NULL;
- }
- #else
- #error Teach me how to get the current working directory.
- #endif
- tmp = &path[strlen(path)];
- sprintf(tmp,"%c%s", FILE_PATH_SEPARATOR, "psm");
- return CMT_EstablishControlConnection(path, &socketFuncs, NULL);
- }
- #define HTTPS_STRING "https://"
- char*
- extract_host_from_url(char *url)
- {
- char *start, *end, *retString=NULL;
- while(isspace(*url)) {
- url++;
- }
- url = strdup(url);
- start = strstr(url, HTTPS_STRING);
- if (start == NULL) {
- return NULL;
- }
- start += strlen(HTTPS_STRING);
- /*
- * Figure out the end of the host name.
- */
- end = strchr(start, ':');
- if (end != NULL) {
- *end = ' ';
- } else {
- end = strchr(start, '/');
- if (end != NULL) {
- *end = ' ';
- } else {
- end = strchr(start, ' ');
- if (end != NULL) {
- *end = ' ';
- }
- }
- }
- retString = strdup(start);
- return retString;
- }
- CMUint32
- get_port_from_url(char *url)
- {
- char *colon, *port;
- url = strdup(url);
- colon = strrchr(url, ':');
- if (colon == NULL ||
- !isdigit(colon[1])) {
- /* Return the default SSL port. */
- free(url);
- return 443;
- }
- colon++;
- port = colon;
- while(isdigit(*colon))
- colon++;
- colon[1] = ' ';
- free(url);
- return (CMUint32)atol(port);
- }
- char*
- extract_get_target(char *url)
- {
- char *slash;
- slash = strstr(url, "//");
- slash += 2;
- slash = strchr(slash, '/');
- if (slash != NULL)
- return strdup (slash);
- else
- return strdup ("/");
- }
- /*
- * We'll use this function for prompting for a password.
- */
- char*
- passwordCallback(void *arg, char *prompt, void *cotext, int isPaswd)
- {
- char input[256];
-
- printf(prompt);
- fgets(input, 256, stdin);
- return strdup(input);
- }
- void
- freeCallback(char *userInput)
- {
- free (userInput);
- }
- #define NUM_PREFS 2
- int
- main(int argc, char **argv)
- {
- PCMT_CONTROL control;
- CMTSocket sock, selSock;
- char *hostname;
- struct hostent *host;
- char *ipAddress;
- char buffer[READ_BUFFER_SIZE];
- size_t bytesRead;
- struct sockaddr_in destAddr;
- char *getString;
- char requestString[256];
- char *profile;
- CMTSetPrefElement prefs[NUM_PREFS];
- char profileDir[256];
- #ifdef WIN32
- WORD WSAVersion = 0x0101;
- WSADATA WSAData;
- WSAStartup (WSAVersion, &WSAData);
- #endif
- if (argc < 2) {
- usage();
- return 1;
- }
- errorMessage (0,"cmtsample v1.0");
- errorMessage (0,"Will try connecting to site %s", argv[1]);
- if (strstr(argv[1], "https://") == NULL) {
- errorMessage(2,"%s is not a secure site", argv[1]);
- }
- control = connect_to_psm();
- if (control == NULL) {
- errorMessage(3, "Could not connect to the psm server");
- }
- /*
- * Now we have to send the hello message.
- */
- #ifdef WIN32
- profile = strdup("default");
- sprintf(profileDir,"%s", "c:\default");
- #elif defined (XP_UNIX)
- profile = getenv("LOGNAME");
- sprintf(profileDir, "%s/.netscape", getenv("HOME"));
- #else
- #error Teach me how to fill in the user profile.
- #endif
- if (CMT_Hello(control, PROTOCOL_VERSION,
- profile, profileDir) != CMTSuccess)
- {
- errorMessage(10, "Failed to send the Hello Message.");
- }
- CMT_SetPromptCallback(control, passwordCallback, NULL);
- CMT_SetAppFreeCallback(control, freeCallback);
- /*
- * Now pass along some preferences to psm. We'll pass hard coded
- * ones here, but apps should figure out a way to manage their user's
- * preferences.
- */
- prefs[0].key = "security.enable_ssl2";
- prefs[0].value = "true";
- prefs[0].type = CMT_PREF_BOOL;
- prefs[1].key = "security.enable_ssl3";
- prefs[1].value = "true";
- prefs[1].type = CMT_PREF_BOOL;
- CMT_PassAllPrefs(control, NUM_PREFS, prefs);
- hostname = extract_host_from_url(argv[1]);
- host = gethostbyname(hostname);
- if (host == NULL) {
- errorMessage(11, "gethostbyname for %s failed", hostname);
- }
- if (host->h_length != 4) {
- errorMessage(4, "Site %s uses IV v6 socket. Not supported by psm.");
- }
-
- /* Create the socket we will use to get the decrypted data back from
- * the psm server.
- */
- sock = APP_GetSocket(0);
- if (sock == NULL) {
- errorMessage(5, "Could not create new socket for communication with "
- "the psm server.");
- }
- memcpy(&(destAddr.sin_addr.s_addr), host->h_addr, host->h_length);
- ipAddress = inet_ntoa(destAddr.sin_addr);
- errorMessage(0, "Mapped %s to the following IP address: %s", argv[1],
- ipAddress);
- if (CMT_OpenSSLConnection(control, sock, SSM_REQUEST_SSL_DATA_SSL,
- get_port_from_url(argv[1]), ipAddress,
- hostname, CM_FALSE, NULL) != CMTSuccess) {
- errorMessage(6, "Could not open SSL connection to %s.", argv[1]);
- }
- getString = extract_get_target(argv[1]);
- sprintf(requestString,
- "GET %s HTTP/1.0rn"
- "rn", getString, hostname);
- APP_Send(sock, requestString, strlen(requestString));
- /*
- * Now all we have to do is sit here and fetch the data from the
- * socket.
- */
- errorMessage (0, "About to print out the fetched page.");
- while ((selSock=APP_Select(&sock, 1, 0)) != NULL) {
- if (selSock == sock) {
- bytesRead = APP_Receive(sock, buffer, READ_BUFFER_SIZE-1);
- if (bytesRead == -1 || bytesRead == 0) {
- break;
- }
- buffer[bytesRead] = ' ';
- fprintf(stderr, buffer);
- }
- }
- fprintf(stderr,"n");
- if (bytesRead == -1) {
- errorMessage(7, "Error receiving decrypted data from psm.");
- }
- errorMessage(0, "Successfully read the entire page.");
- if (CMT_DestroyDataConnection(control, sock) != CMTSuccess) {
- errorMessage(8, "Error destroygin the SSL data connection "
- "with the psm server.");
- }
- if (CMT_CloseControlConnection(control) != CMTSuccess) {
- errorMessage(9, "Error closing the control connection.");
- }
- return 0;
- }