Blame src/init.c

Packit Service 31306d
/*
Packit Service 31306d
 * init.c - initialization and finalization of the library
Packit Service 31306d
 *
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2003-2009 by Aris Adamantiadis
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is free software; you can redistribute it and/or modify
Packit Service 31306d
 * it under the terms of the GNU Lesser General Public License as published by
Packit Service 31306d
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit Service 31306d
 * option) any later version.
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is distributed in the hope that it will be useful, but
Packit Service 31306d
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 31306d
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit Service 31306d
 * License for more details.
Packit Service 31306d
 *
Packit Service 31306d
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 31306d
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit Service 31306d
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit Service 31306d
 * MA 02111-1307, USA.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
#include "libssh/priv.h"
Packit Service 31306d
#include "libssh/socket.h"
Packit Service 31306d
#include "libssh/dh.h"
Packit Service 31306d
#include "libssh/poll.h"
Packit Service 31306d
#include "libssh/threads.h"
Packit Service 31306d
Packit Service 31306d
#ifdef _WIN32
Packit Service 31306d
#include <winsock2.h>
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
Packit Service 31306d
#define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor))
Packit Service 31306d
#else
Packit Service 31306d
#define CONSTRUCTOR_ATTRIBUTE
Packit Service 31306d
#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
Packit Service 31306d
#define DESTRUCTOR_ATTRIBUTE __attribute__((destructor))
Packit Service 31306d
#else
Packit Service 31306d
#define DESTRUCTOR_ATTRIBUTE
Packit Service 31306d
#endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
Packit Service 31306d
Packit Service 31306d
/* Declare static mutex */
Packit Service 31306d
static SSH_MUTEX ssh_init_mutex = SSH_MUTEX_STATIC_INIT;
Packit Service 31306d
Packit Service 31306d
/* Counter for initializations */
Packit Service 31306d
static int _ssh_initialized = 0;
Packit Service 31306d
Packit Service 31306d
/* Cache the returned value */
Packit Service 31306d
static int _ssh_init_ret = 0;
Packit Service 31306d
Packit Service 31306d
void libssh_constructor(void) CONSTRUCTOR_ATTRIBUTE;
Packit Service 31306d
void libssh_destructor(void) DESTRUCTOR_ATTRIBUTE;
Packit Service 31306d
Packit Service 31306d
static int _ssh_init(unsigned constructor) {
Packit Service 31306d
Packit Service 31306d
    int rc = 0;
Packit Service 31306d
Packit Service 31306d
    if (!constructor) {
Packit Service 31306d
        ssh_mutex_lock(&ssh_init_mutex);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    _ssh_initialized++;
Packit Service 31306d
Packit Service 31306d
    if (_ssh_initialized > 1) {
Packit Service 31306d
        rc = _ssh_init_ret;
Packit Service 31306d
        goto _ret;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_threads_init();
Packit Service 31306d
    if (rc) {
Packit Service 31306d
        goto _ret;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_crypto_init();
Packit Service 31306d
    if (rc) {
Packit Service 31306d
        goto _ret;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_dh_init();
Packit Service 31306d
    if (rc) {
Packit Service 31306d
        goto _ret;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_socket_init();
Packit Service 31306d
    if (rc) {
Packit Service 31306d
        goto _ret;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
_ret:
Packit Service 31306d
    _ssh_init_ret = rc;
Packit Service 31306d
Packit Service 31306d
    if (!constructor) {
Packit Service 31306d
        ssh_mutex_unlock(&ssh_init_mutex);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Initialize global cryptographic data structures.
Packit Service 31306d
 *
Packit Service 31306d
 * This functions is automatically called when the library is loaded.
Packit Service 31306d
 *
Packit Service 31306d
 */
Packit Service 31306d
void libssh_constructor(void)
Packit Service 31306d
{
Packit Service 31306d
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    rc = _ssh_init(1);
Packit Service 31306d
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        fprintf(stderr, "Error in auto_init()\n");
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @defgroup libssh The libssh API
Packit Service 31306d
 *
Packit Service 31306d
 * The libssh library is implementing the SSH protocols and some of its
Packit Service 31306d
 * extensions. This group of functions is mostly used to implement an SSH
Packit Service 31306d
 * client.
Packit Service 31306d
 * Some function are needed to implement an SSH server too.
Packit Service 31306d
 *
Packit Service 31306d
 * @{
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Initialize global cryptographic data structures.
Packit Service 31306d
 *
Packit Service 31306d
 * Since version 0.8.0, it is not necessary to call this function on systems
Packit Service 31306d
 * which are fully supported with regards to threading (that is, system with
Packit Service 31306d
 * pthreads available).
Packit Service 31306d
 *
Packit Service 31306d
 * If the library is already initialized, increments the _ssh_initialized
Packit Service 31306d
 * counter and return the error code cached in _ssh_init_ret.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             SSH_OK on success, SSH_ERROR if an error occurred.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_init(void) {
Packit Service 31306d
    return _ssh_init(0);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int _ssh_finalize(unsigned destructor) {
Packit Service 31306d
Packit Service 31306d
    if (!destructor) {
Packit Service 31306d
        ssh_mutex_lock(&ssh_init_mutex);
Packit Service 31306d
Packit Service 31306d
        if (_ssh_initialized > 1) {
Packit Service 31306d
            _ssh_initialized--;
Packit Service 31306d
            goto _ret;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        if (_ssh_initialized == 1) {
Packit Service 31306d
            if (_ssh_init_ret < 0) {
Packit Service 31306d
                goto _ret;
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* If the counter reaches zero or it is the destructor calling, finalize */
Packit Service 31306d
    ssh_dh_finalize();
Packit Service 31306d
    ssh_crypto_finalize();
Packit Service 31306d
    ssh_socket_cleanup();
Packit Service 31306d
    /* It is important to finalize threading after CRYPTO because
Packit Service 31306d
     * it still depends on it */
Packit Service 31306d
    ssh_threads_finalize();
Packit Service 31306d
Packit Service 31306d
    _ssh_initialized = 0;
Packit Service 31306d
Packit Service 31306d
_ret:
Packit Service 31306d
    if (!destructor) {
Packit Service 31306d
        ssh_mutex_unlock(&ssh_init_mutex);
Packit Service 31306d
    }
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Finalize and cleanup all libssh and cryptographic data structures.
Packit Service 31306d
 *
Packit Service 31306d
 * This function is automatically called when the library is unloaded.
Packit Service 31306d
 *
Packit Service 31306d
 */
Packit Service 31306d
void libssh_destructor(void)
Packit Service 31306d
{
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    rc = _ssh_finalize(1);
Packit Service 31306d
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        fprintf(stderr, "Error in libssh_destructor()\n");
Packit Service 31306d
    }
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Finalize and cleanup all libssh and cryptographic data structures.
Packit Service 31306d
 *
Packit Service 31306d
 * Since version 0.8.0, it is not necessary to call this function, since it is
Packit Service 31306d
 * automatically called when the library is unloaded.
Packit Service 31306d
 *
Packit Service 31306d
 * If ssh_init() is called explicitly, then ssh_finalize() must be called
Packit Service 31306d
 * explicitly.
Packit Service 31306d
 *
Packit Service 31306d
 * When called, decrements the counter _ssh_initialized. If the counter reaches
Packit Service 31306d
 * zero, then the libssh and cryptographic data structures are cleaned up.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             0 on succes, -1 if an error occured.
Packit Service 31306d
 *
Packit Service 31306d
 @returns 0 otherwise
Packit Service 31306d
 */
Packit Service 31306d
int ssh_finalize(void) {
Packit Service 31306d
    return _ssh_finalize(0);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef _WIN32
Packit Service 31306d
Packit Service 31306d
#if defined(_MSC_VER) && !defined(LIBSSH_STATIC)
Packit Service 31306d
/* Library constructor and destructor */
Packit Service 31306d
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
Packit Service 31306d
                    DWORD fdwReason,
Packit Service 31306d
                    LPVOID lpvReserved)
Packit Service 31306d
{
Packit Service 31306d
    int rc = 0;
Packit Service 31306d
Packit Service 31306d
    switch(fdwReason) {
Packit Service 31306d
    case DLL_PROCESS_ATTACH:
Packit Service 31306d
        rc = _ssh_init(1);
Packit Service 31306d
        if (rc != 0) {
Packit Service 31306d
            fprintf(stderr, "DllMain: ssh_init failed!");
Packit Service 31306d
            return FALSE;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case DLL_PROCESS_DETACH:
Packit Service 31306d
        _ssh_finalize(1);
Packit Service 31306d
        break;
Packit Service 31306d
    default:
Packit Service 31306d
        break;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return TRUE;
Packit Service 31306d
}
Packit Service 31306d
#endif /* _MSC_VER && !LIBSSH_STATIC */
Packit Service 31306d
Packit Service 31306d
#endif /* _WIN32 */
Packit Service 31306d
Packit Service 31306d
/** @} */