diff options
44 files changed, 5897 insertions, 0 deletions
diff --git a/crypto/openssh/sshlogin.c b/crypto/openssh/sshlogin.c new file mode 100644 index 000000000000..b8536c0bcbcf --- /dev/null +++ b/crypto/openssh/sshlogin.c @@ -0,0 +1,137 @@ +/* + * Author: Tatu Ylonen <ylo@cs.hut.fi> + * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland + * All rights reserved + * This file performs some of the things login(1) normally does. We cannot + * easily use something like login -p -h host -f user, because there are + * several different logins around, and it is hard to determined what kind of + * login the current system has. Also, we want to be able to execute commands + * on a tty. + * + * As far as I am concerned, the code I have written for this software + * can be used freely for any purpose. Any derived versions of this + * software must be clearly marked as such, and if the derived work is + * incompatible with the protocol description in the RFC file, it must be + * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 1999 Theo de Raadt. All rights reserved. + * Copyright (c) 1999 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: sshlogin.c,v 1.2 2001/03/24 16:43:27 stevesk Exp $"); +RCSID("$FreeBSD$"); + +#include <libutil.h> +#include <utmp.h> +#include "sshlogin.h" +#include "log.h" + +/* + * Returns the time when the user last logged in. Returns 0 if the + * information is not available. This must be called before record_login. + * The host the user logged in from will be returned in buf. + */ + +u_long +get_last_login_time(uid_t uid, const char *logname, + char *buf, u_int bufsize) +{ + struct lastlog ll; + char *lastlog; + int fd; + + lastlog = _PATH_LASTLOG; + buf[0] = '\0'; + + fd = open(lastlog, O_RDONLY); + if (fd < 0) + return 0; + lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET); + if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) { + close(fd); + return 0; + } + close(fd); + if (bufsize > sizeof(ll.ll_host) + 1) + bufsize = sizeof(ll.ll_host) + 1; + strncpy(buf, ll.ll_host, bufsize - 1); + buf[bufsize - 1] = 0; + return ll.ll_time; +} + +/* + * Records that the user has logged in. I these parts of operating systems + * were more standardized. + */ + +void +record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid, + const char *host, struct sockaddr * addr) +{ + int fd; + struct lastlog ll; + char *lastlog; + struct utmp u; + + /* Construct an utmp/wtmp entry. */ + memset(&u, 0, sizeof(u)); + strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line)); + u.ut_time = time(NULL); + strncpy(u.ut_name, user, sizeof(u.ut_name)); + realhostname_sa(u.ut_host, sizeof(u.ut_host), addr, addr->sa_len); + + login(&u); + lastlog = _PATH_LASTLOG; + + /* Update lastlog unless actually recording a logout. */ + if (strcmp(user, "") != 0) { + /* + * It is safer to bzero the lastlog structure first because + * some systems might have some extra fields in it (e.g. SGI) + */ + memset(&ll, 0, sizeof(ll)); + + /* Update lastlog. */ + ll.ll_time = time(NULL); + strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line)); + strncpy(ll.ll_host, host, sizeof(ll.ll_host)); + fd = open(lastlog, O_RDWR); + if (fd >= 0) { + lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET); + if (write(fd, &ll, sizeof(ll)) != sizeof(ll)) + log("Could not write %.100s: %.100s", lastlog, strerror(errno)); + close(fd); + } + } +} + +/* Records that the user has logged out. */ + +void +record_logout(pid_t pid, const char *ttyname) +{ + const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */ + if (logout(line)) + logwtmp(line, "", ""); +} diff --git a/crypto/openssl/crypto/uid.c b/crypto/openssl/crypto/uid.c new file mode 100644 index 000000000000..b5b61b76d4e3 --- /dev/null +++ b/crypto/openssl/crypto/uid.c @@ -0,0 +1,88 @@ +/* crypto/uid.c */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <openssl/crypto.h> + +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ > 2) + +#include <unistd.h> + +int OPENSSL_issetugid(void) + { + return issetugid(); + } + +#elif defined(WIN32) + +int OPENSSL_issetugid(void) + { + return 0; + } + +#else + +#include <unistd.h> +#include <sys/types.h> + +int OPENSSL_issetugid(void) + { + if (getuid() != geteuid()) return 1; + if (getgid() != getegid()) return 1; + return 0; + } +#endif + + + diff --git a/crypto/openssl/doc/ssl/SSL_CTX_load_verify_locations.pod b/crypto/openssl/doc/ssl/SSL_CTX_load_verify_locations.pod new file mode 100644 index 000000000000..88f18bd5ff40 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_load_verify_locations.pod @@ -0,0 +1,124 @@ +=pod + +=head1 NAME + +SSL_CTX_load_verify_locations - set default locations for trusted CA +certificates + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); + +=head1 DESCRIPTION + +SSL_CTX_load_verify_locations() specifies the locations for B<ctx>, at +which CA certificates for verification purposes are located. The certificates +available via B<CAfile> and B<CApath> are trusted. + +=head1 NOTES + +If B<CAfile> is not NULL, it points to a file of CA certificates in PEM +format. The file can contain several CA certificates identified by + + -----BEGIN CERTIFICATE----- + ... (CA certificate in base64 encoding) ... + -----END CERTIFICATE----- + +sequences. Before, between, and after the certificates text is allowed +which can be used e.g. for descriptions of the certificates. + +The B<CAfile> is processed on execution of the SSL_CTX_load_verify_locations() +function. + +If on an TLS/SSL server no special setting is performed using *client_CA_list() +functions, the certificates contained in B<CAfile> are listed to the client +as available CAs during the TLS/SSL handshake. + +If B<CApath> is not NULL, it points to a directory containing CA certificates +in PEM format. The files each contain one CA certificate. The files are +looked up by the CA subject name hash value, which must hence be available. +If more than one CA certificate with the same name hash value exist, the +extension must be different (e.g. 9d66eef0.0, 9d66eef0.1 etc). The search +is performed in the ordering of the extension number, regardless of other +properties of the certificates. +Use the B<c_rehash> utility to create the necessary links. + +The certificates in B<CApath> are only looked up when required, e.g. when +building the certificate chain or when actually performing the verification +of a peer certificate. + +On a server, the certificates in B<CApath> are not listed as available +CA certificates to a client during a TLS/SSL handshake. + +When looking up CA certificates, the OpenSSL library will first search the +certificates in B<CAfile>, then those in B<CApath>. Certificate matching +is done based on the subject name, the key identifier (if present), and the +serial number as taken from the certificate to be verified. If these data +do not match, the next certificate will be tried. If a first certificate +matching the parameters is found, the verification process will be performed; +no other certificates for the same parameters will be searched in case of +failure. + +When building its own certificate chain, an OpenSSL client/server will +try to fill in missing certificates from B<CAfile>/B<CApath>, if the +certificate chain was not explicitly specified (see +L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)>, +L<SSL_CTX_use_certificate(3)|SSL_CTX_use_certificate(3)>. + +=head1 WARNINGS + +If several CA certificates matching the name, key identifier, and serial +number condition are available, only the first one will be examined. This +may lead to unexpected results if the same CA certificate is available +with different expiration dates. If a "certificate expired" verification +error occurs, no other certificate will be searched. Make sure to not +have expired certificates mixed with valid ones. + +=head1 EXAMPLES + +Generate a CA certificate file with descriptive text from the CA certificates +ca1.pem ca2.pem ca3.pem: + + #!/bin/sh + rm CAfile.pem + for i in ca1.pem ca2.pem ca3.pem ; do + openssl x509 -in $i -text >> CAfile.pem + done + +Prepare the directory /some/where/certs containing several CA certificates +for use as B<CApath>: + + cd /some/where/certs + c_rehash . + +=head1 RETURN VALUES + +The following return values can occur: + +=over 4 + +=item 0 + +The operation failed because B<CAfile> and B<CApath> are NULL or the +processing at one of the locations specified failed. Check the error +stack to find out the reason. + +=item 1 + +The operation succeeded. + +=back + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, +L<SSL_CTX_set_client_CA_list(3)|SSL_CTX_set_client_CA_list(3)>, +L<SSL_get_client_CA_list(3)|SSL_get_client_CA_list(3)>, +L<SSL_CTX_use_certificate(3)|SSL_CTX_use_certificate(3)>, +L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)> + + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_sess_number.pod b/crypto/openssl/doc/ssl/SSL_CTX_sess_number.pod new file mode 100644 index 000000000000..19aa4e29027b --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_sess_number.pod @@ -0,0 +1,76 @@ +=pod + +=head1 NAME + +SSL_CTX_sess_number, SSL_CTX_sess_connect, SSL_CTX_sess_connect_good, SSL_CTX_sess_connect_renegotiate, SSL_CTX_sess_accept, SSL_CTX_sess_accept_good, SSL_CTX_sess_accept_renegotiate, SSL_CTX_sess_hits, SSL_CTX_sess_cb_hits, SSL_CTX_sess_misses, SSL_CTX_sess_timeouts, SSL_CTX_sess_cache_full - obtain session cache statistics + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + long SSL_CTX_sess_number(SSL_CTX *ctx); + long SSL_CTX_sess_connect(SSL_CTX *ctx); + long SSL_CTX_sess_connect_good(SSL_CTX *ctx); + long SSL_CTX_sess_connect_renegotiate(SSL_CTX *ctx); + long SSL_CTX_sess_accept(SSL_CTX *ctx); + long SSL_CTX_sess_accept_good(SSL_CTX *ctx); + long SSL_CTX_sess_accept_renegotiate(SSL_CTX *ctx); + long SSL_CTX_sess_hits(SSL_CTX *ctx); + long SSL_CTX_sess_cb_hits(SSL_CTX *ctx); + long SSL_CTX_sess_misses(SSL_CTX *ctx); + long SSL_CTX_sess_timeouts(SSL_CTX *ctx); + long SSL_CTX_sess_cache_full(SSL_CTX *ctx); + +=head1 DESCRIPTION + +SSL_CTX_sess_number() returns the current number of sessions in the internal +session cache. + +SSL_CTX_sess_connect() returns the number of started SSL/TLS handshakes in +client mode. + +SSL_CTX_sess_connect_good() returns the number of successfully established +SSL/TLS sessions in client mode. + +SSL_CTX_sess_connect_renegotiate() returns the number of start renegotiations +in client mode. + +SSL_CTX_sess_accept() returns the number of started SSL/TLS handshakes in +server mode. + +SSL_CTX_sess_accept_good() returns the number of successfully established +SSL/TLS sessions in server mode. + +SSL_CTX_sess_accept_renegotiate() returns the number of start renegotiations +in server mode. + +SSL_CTX_sess_hits() returns the number of successfully reused sessions. +In client mode a session set with L<SSL_set_session(3)|SSL_set_session(3)> +successfully reused is counted as a hit. In server mode a session successfully +retrieved from internal or external cache is counted as a hit. + +SSL_CTX_sess_cb_hits() returns the number of successfully retrieved sessions +from the external session cache in server mode. + +SSL_CTX_sess_misses() returns the number of sessions proposed by clients +that were not found in the internal session cache in server mode. + +SSL_CTX_sess_timeouts() returns the number of sessions proposed by clients +and either found in the internal or external session cache in server mode, + but that were invalid due to timeout. These sessions are not included in +the SSL_CTX_sess_hits() count. + +SSL_CTX_sess_cache_full() returns the number of sessions that were removed +because the maximum session cache size was exceeded. + +=head1 RETURN VALUES + +The functions return the values indicated in the DESCRIPTION section. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_set_session(3)|SSL_set_session(3)>, +L<SSL_CTX_set_session_cache_mode(3)|SSL_CTX_set_session_cache_mode(3)> +L<SSL_CTX_sess_set_cache_size(3)|SSL_CTX_sess_set_cache_size(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_sess_set_cache_size.pod b/crypto/openssl/doc/ssl/SSL_CTX_sess_set_cache_size.pod new file mode 100644 index 000000000000..d59a7db636a8 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_sess_set_cache_size.pod @@ -0,0 +1,51 @@ +=pod + +=head1 NAME + +SSL_CTX_sess_set_cache_size, SSL_CTX_sess_get_cache_size - manipulate session cache size + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + long SSL_CTX_sess_set_cache_size(SSL_CTX *ctx, long t); + long SSL_CTX_sess_get_cache_size(SSL_CTX *ctx); + +=head1 DESCRIPTION + +SSL_CTX_sess_set_cache_size() sets the size of the internal session cache +of context B<ctx> to B<t>. + +SSL_CTX_sess_get_cache_size() returns the currently valid session cache size. + +=head1 NOTES + +The internal session cache size is SSL_SESSION_CACHE_MAX_SIZE_DEFAULT, +currently 1024*20, so that up to 20000 sessions can be held. This size +can be modified using the SSL_CTX_sess_set_cache_size() call. A special +case is the size 0, which is used for unlimited size. + +When the maximum number of sessions is reached, no more new sessions are +added to the cache. New space may be added by calling +L<SSL_CTX_flush_sessions(3)|<SSL_CTX_flush_sessions(3)> to remove +expired sessions. + +If the size of the session cache is reduced and more sessions are already +in the session cache, old session will be removed at the next time a +session shall be added. This removal is not synchronized with the +expiration of sessions. + +=head1 RETURN VALUES + +SSL_CTX_sess_set_cache_size() returns the previously valid size. + +SSL_CTX_sess_get_cache_size() returns the currently valid size. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, +L<SSL_CTX_set_session_cache_mode(3)|SSL_CTX_set_session_cache_mode(3)>, +L<SSL_CTX_sess_number(3)|SSL_CTX_sess_number(3)>, +L<SSL_CTX_flush_sessions(3)|<SSL_CTX_flush_sessions(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_sessions.pod b/crypto/openssl/doc/ssl/SSL_CTX_sessions.pod new file mode 100644 index 000000000000..e05aab3c1bc2 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_sessions.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +SSL_CTX_sessions - access internal session cache + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx); + +=head1 DESCRIPTION + +SSL_CTX_sessions() returns a pointer to the lhash databases containing the +internal session cache for B<ctx>. + +=head1 NOTES + +The sessions in the internal session cache are kept in an +L<lhash(3)|lhash(3)> type database. It is possible to directly +access this database e.g. for searching. In parallel, the sessions +form a linked list which is maintained separately from the +L<lhash(3)|lhash(3)> operations, so that the database must not be +modified directly but by using the +L<SSL_CTX_add_session(3)|SSL_CTX_add_session(3)> family of functions. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<lhash(3)|lhash(3)>, +L<SSL_CTX_add_session(3)|SSL_CTX_add_session(3)>, +L<SSL_CTX_set_session_cache_mode(3)|SSL_CTX_set_session_cache_mode(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_client_CA_list.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_client_CA_list.pod new file mode 100644 index 000000000000..81e312761e7a --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_set_client_CA_list.pod @@ -0,0 +1,90 @@ +=pod + +=head1 NAME + +SSL_CTX_set_client_CA_list, SSL_set_client_CA_list, SSL_CTX_add_client_CA, +SSL_add_client_CA - set list of CAs sent to the client when requesting a +client certificate + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *list); + void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *list); + int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *cacert); + int SSL_add_client_CA(SSL *ssl, X509 *cacert); + +=head1 DESCRIPTION + +SSL_CTX_set_client_CA_list() sets the B<list> of CAs sent to the client when +requesting a client certificate for B<ctx>. + +SSL_set_client_CA_list() sets the B<list> of CAs sent to the client when +requesting a client certificate for the chosen B<ssl>, overriding the +setting valid for B<ssl>'s SSL_CTX object. + +SSL_CTX_add_client_CA() adds the CA name extracted from B<cacert> to the +list of CAs sent to the client when requesting a client certificate for +B<ctx>. + +SSL_add_client_CA() adds the CA name extracted from B<cacert> to the +list of CAs sent to the client when requesting a client certificate for +the chosen B<ssl>, overriding the setting valid for B<ssl>'s SSL_CTX object. + +=head1 NOTES + +When a TLS/SSL server requests a client certificate (see +B<SSL_CTX_set_verify_options()>), it sends a list of CAs, for which +it will accept certificates, to the client. If no special list is provided, +the CAs available using the B<CAfile> option in +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)> +are sent. + +This list can be explicitly set using the SSL_CTX_set_client_CA_list() for +B<ctx> and SSL_set_client_CA_list() for the specific B<ssl>. The list +specified overrides the previous setting. The CAs listed do not become +trusted (B<list> only contains the names, not the complete certificates); use +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)> +to additionally load them for verification. + +SSL_CTX_add_client_CA() and SSL_add_client_CA() can be used to add additional +items the list of client CAs. If no list was specified before using +SSL_CTX_set_client_CA_list() or SSL_set_client_CA_list(), a new client +CA list for B<ctx> or B<ssl> (as appropriate) is opened. The CAs implicitly +specified using +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)> +are no longer used automatically. + +These functions are only useful for TLS/SSL servers. + +=head1 RETURN VALUES + +SSL_CTX_set_client_CA_list() and SSL_set_client_CA_list() do not return +diagnostic information. + +SSL_CTX_add_client_CA() and SSL_add_client_CA() have the following return +values: + +=over 4 + +=item 1 + +The operation succeeded. + +=item 0 + +A failure while manipulating the STACK_OF(X509_NAME) object occurred or +the X509_NAME could not be extracted from B<cacert>. Check the error stack +to find out the reason. + +=back + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, +L<SSL_get_client_CA_list(3)|SSL_get_client_CA_list(3)>, +L<SSL_load_client_CA_file(3)|SSL_load_client_CA_file(3)> +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_mode.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_mode.pod new file mode 100644 index 000000000000..9a035bb4d184 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_set_mode.pod @@ -0,0 +1,78 @@ +=pod + +=head1 NAME + +SSL_CTX_set_mode, SSL_set_mode, SSL_CTX_get_mode, SSL_get_mode - manipulate SSL engine mode + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + long SSL_CTX_set_mode(SSL_CTX *ctx, long mode); + long SSL_set_mode(SSL *ssl, long mode); + + long SSL_CTX_get_mode(SSL_CTX *ctx); + long SSL_get_mode(SSL *ssl); + +=head1 DESCRIPTION + +SSL_CTX_set_mode() adds the mode set via bitmask in B<mode> to B<ctx>. +Options already set before are not cleared. + +SSL_set_mode() adds the mode set via bitmask in B<mode> to B<ssl>. +Options already set before are not cleared. + +SSL_CTX_get_mode() returns the mode set for B<ctx>. + +SSL_get_mode() returns the mode set for B<ssl>. + +=head1 NOTES + +The following mode changes are available: + +=over 4 + +=item SSL_MODE_ENABLE_PARTIAL_WRITE + +Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success +when just a single record has been written). When not set (the default), +SSL_write() will only report success once the complete chunk was written. + +=item SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + +Make it possible to retry SSL_write() with changed buffer location +(the buffer contents must stay the same). This is not the default to avoid +the misconception that non-blocking SSL_write() behaves like +non-blocking write(). + +=item SSL_MODE_AUTO_RETRY + +Never bother the application with retries if the transport is blocking. +If a renegotiation take place during normal operation, a +L<SSL_read(3)|SSL_read(3)> or L<SSL_write(3)|SSL_write(3)> would return +with -1 and indicate the need to retry with SSL_ERROR_WANT_READ. +In a non-blocking environment applications must be prepared to handle +incomplete read/write operations. +In a blocking environment, applications are not always prepared to +deal with read/write operations returning without success report. The +flag SSL_MODE_AUTO_RETRY will cause read/write operations to only +return after the handshake and successful completion. + +=back + +=head1 RETURN VALUES + +SSL_CTX_set_mode() and SSL_set_mode() return the new mode bitmask +after adding B<mode>. + +SSL_CTX_get_mode() and SSL_get_mode() return the current bitmask. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_read(3)|SSL_read(3)>, L<SSL_write(3)|SSL_write(3)> + +=head1 HISTORY + +SSL_MODE_AUTO_RETRY as been added in OpenSSL 0.9.6. + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_options.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_options.pod new file mode 100644 index 000000000000..3dc7cc74ad63 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_set_options.pod @@ -0,0 +1,183 @@ +=pod + +=head1 NAME + +SSL_CTX_set_options, SSL_set_options, SSL_CTX_get_options, SSL_get_options - manipulate SSL engine options + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + long SSL_CTX_set_options(SSL_CTX *ctx, long options); + long SSL_set_options(SSL *ssl, long options); + + long SSL_CTX_get_options(SSL_CTX *ctx); + long SSL_get_options(SSL *ssl); + +=head1 DESCRIPTION + +SSL_CTX_set_options() adds the options set via bitmask in B<options> to B<ctx>. +Options already set before are not cleared. + +SSL_set_options() adds the options set via bitmask in B<options> to B<ssl>. +Options already set before are not cleared. + +SSL_CTX_get_options() returns the options set for B<ctx>. + +SSL_get_options() returns the options set for B<ssl>. + +=head1 NOTES + +The behaviour of the SSL library can be changed by setting several options. +The options are coded as bitmasks and can be combined by a logical B<or> +operation (|). Options can only be added but can never be reset. + +During a handshake, the option settings of the SSL object used. When +a new SSL object is created from a context using SSL_new(), the current +option setting is copied. Changes to B<ctx> do not affect already created +SSL objects. SSL_clear() does not affect the settings. + +The following B<bug workaround> options are available: + +=over 4 + +=item SSL_OP_MICROSOFT_SESS_ID_BUG + +www.microsoft.com - when talking SSLv2, if session-id reuse is +performed, the session-id passed back in the server-finished message +is different from the one decided upon. + +=item SSL_OP_NETSCAPE_CHALLENGE_BUG + +Netscape-Commerce/1.12, when talking SSLv2, accepts a 32 byte +challenge but then appears to only use 16 bytes when generating the +encryption keys. Using 16 bytes is ok but it should be ok to use 32. +According to the SSLv3 spec, one should use 32 bytes for the challenge +when operating in SSLv2/v3 compatibility mode, but as mentioned above, +this breaks this server so 16 bytes is the way to go. + +=item SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + +ssl3.netscape.com:443, first a connection is established with RC4-MD5. +If it is then resumed, we end up using DES-CBC3-SHA. It should be +RC4-MD5 according to 7.6.1.3, 'cipher_suite'. + +Netscape-Enterprise/2.01 (https://merchant.netscape.com) has this bug. +It only really shows up when connecting via SSLv2/v3 then reconnecting +via SSLv3. The cipher list changes.... + +NEW INFORMATION. Try connecting with a cipher list of just +DES-CBC-SHA:RC4-MD5. For some weird reason, each new connection uses +RC4-MD5, but a re-connect tries to use DES-CBC-SHA. So netscape, when +doing a re-connect, always takes the first cipher in the cipher list. + +=item SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG + +... + +=item SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER + +... + +=item SSL_OP_MSIE_SSLV2_RSA_PADDING + +... + +=item SSL_OP_SSLEAY_080_CLIENT_DH_BUG + +... + +=item SSL_OP_TLS_D5_BUG + +... + +=item SSL_OP_TLS_BLOCK_PADDING_BUG + +... + +=item SSL_OP_TLS_ROLLBACK_BUG + +Disable version rollback attack detection. + +During the client key exchange, the client must send the same information +about acceptable SSL/TLS protocol levels as during the first hello. Some +clients violate this rule by adapting to the server's answer. (Example: +the client sends a SSLv2 hello and accepts up to SSLv3.1=TLSv1, the server +only understands up to SSLv3. In this case the client must still use the +same SSLv3.1=TLSv1 announcement. Some clients step down to SSLv3 with respect +to the server's answer and violate the version rollback protection.) + +=item SSL_OP_ALL + +All of the above bug workarounds. + +=back + +It is save and recommended to use SSL_OP_ALL to enable the bug workaround +options. + +The following B<modifying> options are available: + +=over 4 + +=item SSL_OP_SINGLE_DH_USE + +Always create a new key when using temporary DH parameters. + +=item SSL_OP_EPHEMERAL_RSA + +Also use the temporary RSA key when doing RSA operations. + +=item SSL_OP_PKCS1_CHECK_1 + +... + +=item SSL_OP_PKCS1_CHECK_2 + +... + +=item SSL_OP_NETSCAPE_CA_DN_BUG + +If we accept a netscape connection, demand a client cert, have a +non-self-sighed CA which does not have it's CA in netscape, and the +browser has a cert, it will crash/hang. Works for 3.x and 4.xbeta + +=item SSL_OP_NON_EXPORT_FIRST + +On servers try to use non-export (stronger) ciphers first. This option does +not work under all circumstances (in the code it is declared "broken"). + +=item SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + +... + +=item SSL_OP_NO_SSLv2 + +Do not use the SSLv2 protocol. + +=item SSL_OP_NO_SSLv3 + +Do not use the SSLv3 protocol. + +=item SSL_OP_NO_TLSv1 + +Do not use the TLSv1 protocol. + +=back + +=head1 RETURN VALUES + +SSL_CTX_set_options() and SSL_set_options() return the new options bitmask +after adding B<options>. + +SSL_CTX_get_options() and SSL_get_options() return the current bitmask. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_new(3)|SSL_new(3)>, L<SSL_clear(3)|SSL_clear(3)> + +=head1 HISTORY + +SSL_OP_TLS_ROLLBACK_BUG has been added in OpenSSL 0.9.6. + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_session_cache_mode.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_session_cache_mode.pod new file mode 100644 index 000000000000..083766f8d084 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_set_session_cache_mode.pod @@ -0,0 +1,107 @@ +=pod + +=head1 NAME + +SSL_CTX_set_session_cache_mode, SSL_CTX_get_session_cache_mode - enable/disable session caching + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + long SSL_CTX_set_session_cache_mode(SSL_CTX ctx, long mode); + long SSL_CTX_get_session_cache_mode(SSL_CTX ctx); + +=head1 DESCRIPTION + +SSL_CTX_set_session_cache_mode() enables/disables session caching +by setting the operational mode for B<ctx> to <mode>. + +SSL_CTX_get_session_cache_mode() returns the currently used cache mode. + +=head1 NOTES + +The OpenSSL library can store/retrieve SSL/TLS sessions for later reuse. +The sessions can be held in memory for each B<ctx>, if more than one +SSL_CTX object is being maintained, the sessions are unique for each SSL_CTX +object. + +In order to reuse a session, a client must send the session's id to the +server. It can only send exactly one id. The server then decides whether it +agrees in reusing the session or starts the handshake for a new session. + +A server will lookup up the session in its internal session storage. If +the session is not found in internal storage or internal storage is +deactivated, the server will try the external storage if available. + +Since a client may try to reuse a session intended for use in a different +context, the session id context must be set by the server (see +L<SSL_CTX_set_session_id_context(3)|SSL_CTX_set_session_id_context(3)>). + +The following session cache modes and modifiers are available: + +=over 4 + +=item SSL_SESS_CACHE_OFF + +No session caching for client or server takes place. + +=item SSL_SESS_CACHE_CLIENT + +Client sessions are added to the session cache. As there is no reliable way +for the OpenSSL library to know whether a session should be reused or which +session to choose (due to the abstract BIO layer the SSL engine does not +have details about the connection), the application must select the session +to be reused by using the L<SSL_set_session(3)|SSL_set_session(3)> +function. This option is not activated by default. + +=item SSL_SESS_CACHE_SERVER + +Server sessions are added to the session cache. When a client proposes a +session to be reused, the session is looked up in the internal session cache. +If the session is found, the server will try to reuse the session. +This is the default. + +=item SSL_SESS_CACHE_BOTH + +Enable both SSL_SESS_CACHE_CLIENT and SSL_SESS_CACHE_SERVER at the same time. + +=item SSL_SESS_CACHE_NO_AUTO_CLEAR + +Normally the session cache is checked for expired sessions every +255 connections using the +L<SSL_CTX_flush_sessions(3)|SSL_CTX_flush_sessions(3)> function. Since +this may lead to a delay which cannot be controlled, the automatic +flushing may be disabled and +L<SSL_CTX_flush_sessions(3)|SSL_CTX_flush_sessions(3)> can be called +explicitly by the application. + +=item SSL_SESS_CACHE_NO_INTERNAL_LOOKUP + +By setting this flag sessions are cached in the internal storage but +they are not looked up automatically. If an external session cache +is enabled, sessions are looked up in the external cache. As automatic +lookup only applies for SSL/TLS servers, the flag has no effect on +clients. + +=back + +The default mode is SSL_SESS_CACHE_SERVER. + +=head1 RETURN VALUES + +SSL_CTX_set_session_cache_mode() returns the previously set cache mode. + +SSL_CTX_get_session_cache_mode() returns the currently set cache mode. + + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_set_session(3)|SSL_set_session(3)>, +L<SSL_CTX_sess_number(3)|SSL_CTX_sess_number(3)>, +L<SSL_CTX_sess_set_cache_size(3)|SSL_CTX_sess_set_cache_size(3)>, +L<SSL_CTX_sess_set_get_cb(3)|SSL_CTX_sess_set_get_cb(3)>, +L<SSL_CTX_set_session_id_context(3)|SSL_CTX_set_session_id_context(3)>, +L<SSL_CTX_set_timeout.pod(3)|SSL_CTX_set_timeout.pod(3)>, +L<SSL_CTX_flush_sessions(3)|SSL_CTX_flush_sessions(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_CTX_use_certificate.pod b/crypto/openssl/doc/ssl/SSL_CTX_use_certificate.pod new file mode 100644 index 000000000000..3b2fe6fc5081 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_CTX_use_certificate.pod @@ -0,0 +1,154 @@ +=pod + +=head1 NAME + +SSL_CTX_use_certificate, SSL_CTX_use_certificate_ASN1, SSL_CTX_use_certificate_file, SSL_use_certificate, SSL_use_certificate_ASN1, SSL_use_certificate_file, SSL_CTX_use_certificate_chain_file, SSL_CTX_use_PrivateKey, SSL_CTX_use_PrivateKey_ASN1, SSL_CTX_use_PrivateKey_file, SSL_CTX_use_RSAPrivateKey, SSL_CTX_use_RSAPrivateKey_ASN1, SSL_CTX_use_RSAPrivateKey_file, SSL_use_PrivateKey_file, SSL_use_PrivateKey_ASN1, SSL_use_PrivateKey, SSL_use_RSAPrivateKey, SSL_use_RSAPrivateKey_ASN1, SSL_use_RSAPrivateKey_file, SSL_CTX_check_private_key, SSL_check_private_key - load certificate and key data + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); + int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d); + int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); + int SSL_use_certificate(SSL *ssl, X509 *x); + int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len); + int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + + int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); + + int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); + int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d, + long len); + int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); + int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); + int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len); + int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); + int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); + int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, unsigned char *d, long len); + int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); + int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); + int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); + int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); + + int SSL_CTX_check_private_key(SSL_CTX *ctx); + int SSL_check_private_key(SSL *ssl); + +=head1 DESCRIPTION + +These functions load the certificates and private keys into the SSL_CTX +or SSL object, respectively. + +The SSL_CTX_* class of functions loads the certificates and keys into the +SSL_CTX object B<ctx>. The information is passed to SSL objects B<ssl> +created from B<ctx> with L<SSL_new(3)|SSL_new(3)> by copying, so that +changes applied to B<ctx> do not propagate to already existing SSL objects. + +The SSL_* class of functions only loads certificates and keys into a +specific SSL object. The specific information is kept, when +L<SSL_clear(3)|SSL_clear(3)> is called for this SSL object. + +SSL_CTX_use_certificate() loads the certificate B<x> into B<ctx>, +SSL_use_certificate() loads B<x> into B<ssl>. The rest of the +certificates needed to form the complete certificate chain can be +specified using the +L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)> +function. + +SSL_CTX_use_certificate_ASN1() loads the ASN1 encoded certificate from +the memory location B<d> (with length B<len>) into B<ctx>, +SSL_use_certificate_ASN1() loads the ASN1 encoded certificate into B<ssl>. + +SSL_CTX_use_certificate_file() loads the first certificate stored in B<file> +into B<ctx>. The formatting B<type> of the certificate must be specified +from the known types SSL_FILETYPE_PEM, SSL_FILETYPE_ASN1. +SSL_use_certificate_file() loads the certificate from B<file> into B<ssl>. +See the NOTES section on why SSL_CTX_use_certificate_chain_file() +should be preferred. + +SSL_CTX_use_certificate_chain_file() loads a certificate chain from +B<file> into B<ctx>. The certificates must be in PEM format and must +be sorted starting with the certificate to the highest level (root CA). +There is no corresponding function working on a single SSL object. + +SSL_CTX_use_PrivateKey() adds B<pkey> as private key to B<ctx>. +SSL_CTX_use_RSAPrivateKey() adds the private key B<rsa> of type RSA +to B<ctx>. SSL_use_PrivateKey() adds B<pkey> as private key to B<ssl>; +SSL_use_RSAPrivateKey() adds B<rsa> as private key of type RSA to B<ssl>. + +SSL_CTX_use_PrivateKey_ASN1() adds the private key of type B<pk> +stored at memory location B<d> (length B<len>) to B<ctx>. +SSL_CTX_use_RSAPrivateKey_ASN1() adds the private key of type RSA +stored at memory location B<d> (length B<len>) to B<ctx>. +SSL_use_PrivateKey_ASN1() and SSL_use_RSAPrivateKey_ASN1() add the private +key to B<ssl>. + +SSL_CTX_use_PrivateKey_file() adds the first private key found in +B<file> to B<ctx>. The formatting B<type> of the certificate must be specified +from the known types SSL_FILETYPE_PEM, SSL_FILETYPE_ASN1. +SSL_CTX_use_RSAPrivateKey_file() adds the first private RSA key found in +B<file> to B<ctx>. SSL_use_PrivateKey_file() adds the first private key found +in B<file> to B<ssl>; SSL_use_RSAPrivateKey_file() adds the first private +RSA key found to B<ssl>. + +SSL_CTX_check_private_key() checks the consistency of a private key with +the corresponding certificate loaded into B<ctx>. If more than one +key/certificate pair (RSA/DSA) is installed, the last item installed will +be checked. If e.g. the last item was a RSA certificate or key, the RSA +key/certificate pair will be checked. SSL_check_private_key() performs +the same check for B<ssl>. If no key/certificate was explicitly added for +this B<ssl>, the last item added into B<ctx> will be checked. + +=head1 NOTES + +The internal certificate store of OpenSSL can hold two private key/certificate +pairs at a time: one key/certificate of type RSA and one key/certificate +of type DSA. The certificate used depends on the cipher select, see +also L<SSL_CTX_set_cipher_list(3)|SSL_CTX_set_cipher_list(3)>. + +When reading certificates and private keys from file, files of type +SSL_FILETYPE_ASN1 (also known as B<DER>, binary encoding) can only contain +one certificate or private key, consequently +SSL_CTX_use_certificate_chain_file() is only applicable to PEM formatting. +Files of type SSL_FILETYPE_PEM can contain more than one item. + +SSL_CTX_use_certificate_chain_file() adds the first certificate found +in the file to the certificate store. The other certificates are added +to the store of chain certificates using +L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)>. +There exists only one extra chain store, so that the same chain is appended +to both types of certificates, RSA and DSA! If it is not intended to use +both type of certificate at the same time, it is recommended to use the +SSL_CTX_use_certificate_chain_file() instead of the +SSL_CTX_use_certificate_file() function in order to allow the use of +complete certificate chains even when no trusted CA storage is used or +when the CA issuing the certificate shall not be added to the trusted +CA storage. + +If additional certificates are needed to complete the chain during the +TLS negotiation, CA certificates are additionally looked up in the +locations of trusted CA certificates, see +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)>. + +The private keys loaded from file can be encrypted. In order to successfully +load encrypted keys, a function returning the passphrase must have been +supplied, see +L<SSL_CTX_set_default_passwd_cb(3)|SSL_CTX_set_default_passwd_cb(3)>. +(Certificate files might be encrypted as well from the technical point +of view, it however does not make sense as the data in the certificate +is considered public anyway.) + +=head1 RETURN VALUES + +On success, the functions return 1. +Otherwise check out the error stack to find out the reason. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_new(3)|SSL_new(3)>, L<SSL_clear(3)|SSL_clear(3)>, +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)>, +L<SSL_CTX_set_default_passwd_cb(3)|SSL_CTX_set_default_passwd_cb(3)>, +L<SSL_CTX_set_cipher_list(3)|SSL_CTX_set_cipher_list(3)>, +L<SSL_CTX_add_extra_chain_cert(3)|SSL_CTX_add_extra_chain_cert(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_get_client_CA_list.pod b/crypto/openssl/doc/ssl/SSL_get_client_CA_list.pod new file mode 100644 index 000000000000..40e01cf9c81e --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_get_client_CA_list.pod @@ -0,0 +1,52 @@ +=pod + +=head1 NAME + +SSL_get_client_CA_list, SSL_CTX_get_client_CA_list - get list of client CAs + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + STACK_OF(X509_NAME) *SSL_get_client_CA_list(SSL *s); + STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(SSL_CTX *ctx); + +=head1 DESCRIPTION + +SSL_CTX_get_client_CA_list() returns the list of client CAs explicitly set for +B<ctx> using L<SSL_CTX_set_client_CA_list(3)|SSL_CTX_set_client_CA_list(3)>. + +SSL_get_client_CA_list() returns the list of client CAs explicitly +set for B<ssl> using SSL_set_client_CA_list() or B<ssl>'s SSL_CTX object with +L<SSL_CTX_set_client_CA_list(3)|SSL_CTX_set_client_CA_list(3)>, when in +server mode. In client mode, SSL_get_client_CA_list returns the list of +client CAs sent from the server, if any. + +=head1 RETURN VALUES + +SSL_CTX_set_client_CA_list() and SSL_set_client_CA_list() do not return +diagnostic information. + +SSL_CTX_add_client_CA() and SSL_add_client_CA() have the following return +values: + +=over 4 + +=item STACK_OF(X509_NAMES) + +List of CA names explicitly set (for B<ctx> or in server mode) or send +by the server (client mode). + +=item NULL + +No client CA list was explicitly set (for B<ctx> or in server mode) or +the server did not send a list of CAs (client mode). + +=back + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, +L<SSL_CTX_set_client_CA_list(3)|SSL_CTX_set_client_CA_list(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_get_version.pod b/crypto/openssl/doc/ssl/SSL_get_version.pod new file mode 100644 index 000000000000..24d52912565d --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_get_version.pod @@ -0,0 +1,46 @@ +=pod + +=head1 NAME + +SSL_get_version - get the protocol version of a connection. + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + const char *SSL_get_version(SSL *ssl); + +=head1 DESCRIPTION + +SSL_get_cipher_version() returns the name of the protocol used for the +connection B<ssl>. + +=head1 RETURN VALUES + +The following strings can occur: + +=over 4 + +=item SSLv2 + +The connection uses the SSLv2 protocol. + +=item SSLv3 + +The connection uses the SSLv3 protocol. + +=item TLSv1 + +The connection uses the TLSv1 protocol. + +=item unknown + +This indicates that no version has been set (no connection established). + +=back + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_set_connect_state.pod b/crypto/openssl/doc/ssl/SSL_set_connect_state.pod new file mode 100644 index 000000000000..a8c4463c640a --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_set_connect_state.pod @@ -0,0 +1,47 @@ +=pod + +=head1 NAME + +SSL_set_connect_state, SSL_get_accept_state - prepare SSL object to work in client or server mode + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + void SSL_set_connect_state(SSL *ssl); + + void SSL_set_accept_state(SSL *ssl); + +=head1 DESCRIPTION + +SSL_set_connect_state() B<ssl> to work in client mode. + +SSL_set_accept_state() B<ssl> to work in server mode. + +=head1 NOTES + +When the SSL_CTX object was created with L<SSL_CTX_new(3)|SSL_CTX_new(3)>, +it was either assigned a dedicated client method, a dedicated server +method, or a generic method, that can be used for both client and +server connections. (The method might have been changed with +L<SSL_CTX_set_ssl_version(3)|SSL_CTX_set_ssl_version(3)> or +SSL_set_ssl_method().) + +In order to successfully accomplish the handshake, the SSL routines need +to know whether they should act in server or client mode. If the generic +method was used, this is not clear from the method itself and must be set +with either SSL_set_connect_state() or SSL_set_accept_state(). If these +routines are not called, the default value set when L<SSL_new(3)|SSL_new(3)> +is called is server mode. + +=head1 RETURN VALUES + +SSL_set_connect_state() and SSL_set_accept_state() do not return diagnostic +information. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_new(3)|SSL_new(3)>, L<SSL_CTX_new(3)|SSL_CTX_new(3)>, +L<SSL_CTX_set_ssl_version(3)|SSL_CTX_set_ssl_version(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/SSL_set_shutdown.pod b/crypto/openssl/doc/ssl/SSL_set_shutdown.pod new file mode 100644 index 000000000000..6b196c1f15b8 --- /dev/null +++ b/crypto/openssl/doc/ssl/SSL_set_shutdown.pod @@ -0,0 +1,68 @@ +=pod + +=head1 NAME + +SSL_set_shutdown, SSL_get_shutdown - manipulate shutdown state of an SSL connection + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + void SSL_set_shutdown(SSL *ssl, int mode); + + int SSL_get_shutdown(SSL *ssl); + +=head1 DESCRIPTION + +SSL_set_shutdown() sets the shutdown state of B<ssl> to B<mode>. + +SSL_get_shutdown() returns the shutdown mode of B<ssl>. + +=head1 NOTES + +The shutdown state of an ssl connection is a bitmask of: + +=over 4 + +=item 0 + +No shutdown setting, yet. + +=item SSL_SENT_SHUTDOWN + +A "close notify" shutdown alert was sent to the peer, the connection is being +considered closed and the session is closed and correct. + +=item SSL_RECEIVED_SHUTDOWN + +A shutdown alert was received form the peer, either a normal "close notify" +or a fatal error. + +=back + +SSL_SENT_SHUTDOWN and SSL_RECEIVED_SHUTDOWN can be set at the same time. + +The shutdown state of the connection is used to determine the state of +the ssl session. If the session is still open, when +L<SSL_clear(3)|SSL_clear(3)> or L<SSL_free(3)|SSL_free(3)> is called, +it is considered bad and removed according to RFC2246. +The actual condition for a correctly closed session is SSL_SENT_SHUTDOWN. +SSL_set_shutdown() can be used to set this state without sending a +close alert to the peer (see L<SSL_shutdown(3)|SSL_shutdown(3)>). + +If a "close notify" was received, SSL_RECEIVED_SHUTDOWN will be set, +for setting SSL_SENT_SHUTDOWN the application must however still call +L<SSL_shutdown(3)|SSL_shutdown(3)> or SSL_set_shutdown() itself. + +=head1 RETURN VALUES + +SSL_set_shutdown() does not return diagnostic information. + +SSL_get_shutdown() returns the current setting. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_shutdown(3)|SSL_shutdown(3)>, +L<SSL_clear(3)|SSL_clear(3)>, L<SSL_free(3)|SSL_free(3)> + +=cut diff --git a/crypto/openssl/doc/ssl/d2i_SSL_SESSION.pod b/crypto/openssl/doc/ssl/d2i_SSL_SESSION.pod new file mode 100644 index 000000000000..9a1ba6c47b21 --- /dev/null +++ b/crypto/openssl/doc/ssl/d2i_SSL_SESSION.pod @@ -0,0 +1,56 @@ +=pod + +=head1 NAME + +d2i_SSL_SESSION, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 representation + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, long length); + int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); + +=head1 DESCRIPTION + +d2i_SSL_SESSION() transforms the external ASN1 representation of an SSL/TLS +session, stored as binary data at location B<pp> with length B<length>, into +an SSL_SESSION object. + +i2d_SSL_SESSION() transforms the SSL_SESSION object B<in> into the ASN1 +representation and stores it into the memory location pointed to by B<pp>. +The length of the resulting ASN1 representation is returned. If B<pp> is +the NULL pointer, only the length is calculated and returned. + +=head1 NOTES + +The SSL_SESSION object is built from several malloc()ed parts, it can +therefore not be moved, copied or stored directly. In order to store +session data on disk or into a database, it must be transformed into +a binary ASN1 representation. + +When using d2i_SSL_SESSION(), the SSL_SESSION object is automatically +allocated. + +When using i2d_SSL_SESSION(), the memory location pointed to by B<pp> must be +large enough to hold the binary representation of the session. There is no +known limit on the size of the created ASN1 representation, so the necessary +amount of space should be obtained by first calling i2d_SSL_SESSION() with +B<pp=NULL>, and obtain the size needed, then allocate the memory and +call i2d_SSL_SESSION() again. + +=head1 RETURN VALUES + +d2i_SSL_SESSION() returns a pointer to the newly allocated SSL_SESSION +object. In case of failure the NULL-pointer is returned and the error message +can be retrieved from the error stack. + +i2d_SSL_SESSION() returns the size of the ASN1 representation in bytes. +When the session is not valid, B<0> is returned and no operation is performed. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, +L<SSL_CTX_sess_set_get_cb(3)|SSL_CTX_sess_set_get_cb(3)> + +=cut diff --git a/crypto/openssl/test/bctest b/crypto/openssl/test/bctest new file mode 100755 index 000000000000..17b75d4ecabd --- /dev/null +++ b/crypto/openssl/test/bctest @@ -0,0 +1,96 @@ +#!/bin/sh + +# This script is used by test/Makefile.ssl to check whether a sane 'bc' +# is installed. +# ('make test_bn' should not try to run 'bc' if it does not exist or if +# it is a broken 'bc' version that is known to cause trouble.) +# +# If 'bc' works, we also test if it knows the 'print' command. +# +# In any case, output an appropriate command line for running (or not +# running) bc. + + +IFS=: +for dir in $PATH; do + bc="$dir/bc" + + if [ -x "$bc" -a ! -d "$bc" ]; then + failure=none + + + # Test for SunOS 5.[78] bc bug + "$bc" >tmp.bctest <<\EOF +obase=16 +ibase=16 +a=AD88C418F31B3FC712D0425001D522B3AE9134FF3A98C13C1FCC1682211195406C1A6C66C6A\ +CEEC1A0EC16950233F77F1C2F2363D56DD71A36C57E0B2511FC4BA8F22D261FE2E9356D99AF57\ +10F3817C0E05BF79C423C3F66FDF321BE8D3F18F625D91B670931C1EF25F28E489BDA1C5422D1\ +C3F6F7A1AD21585746ECC4F10A14A778AF56F08898E965E9909E965E0CB6F85B514150C644759\ +3BE731877B16EA07B552088FF2EA728AC5E0FF3A23EB939304519AB8B60F2C33D6BA0945B66F0\ +4FC3CADF855448B24A9D7640BCF473E +b=DCE91E7D120B983EA9A104B5A96D634DD644C37657B1C7860B45E6838999B3DCE5A555583C6\ +9209E41F413422954175A06E67FFEF6746DD652F0F48AEFECC3D8CAC13523BDAAD3F5AF4212BD\ +8B3CD64126E1A82E190228020C05B91C8B141F1110086FC2A4C6ED631EBA129D04BB9A19FC53D\ +3ED0E2017D60A68775B75481449 +(a/b)*b + (a%b) - a +EOF + if [ 0 != "`cat tmp.bctest`" ]; then + failure=SunOStest + fi + + + if [ "$failure" = none ]; then + # Test for SCO bc bug. + "$bc" >tmp.bctest <<\EOF +obase=16 +ibase=16 +-FFDD63BA1A4648F0D804F8A1C66C53F0D2110590E8A3907EC73B4AEC6F15AC177F176F2274D2\ +9DC8022EA0D7DD3ABE9746D2D46DD3EA5B5F6F69DF12877E0AC5E7F5ADFACEE54573F5D256A06\ +11B5D2BC24947724E22AE4EC3FB0C39D9B4694A01AFE5E43B4D99FB9812A0E4A5773D8B254117\ +1239157EC6E3D8D50199 * -FFDD63BA1A4648F0D804F8A1C66C53F0D2110590E8A3907EC73B4\ +AEC6F15AC177F176F2274D29DC8022EA0D7DD3ABE9746D2D46DD3EA5B5F6F69DF12877E0AC5E7\ +F5ADFACEE54573F5D256A0611B5D2BC24947724E22AE4EC3FB0C39D9B4694A01AFE5E43B4D99F\ +B9812A0E4A5773D8B2541171239157EC6E3D8D50199 - FFBACC221682DA464B6D7F123482522\ +02EDAEDCA38C3B69E9B7BBCD6165A9CD8716C4903417F23C09A85B851961F92C217258CEEB866\ +85EFCC5DD131853A02C07A873B8E2AF2E40C6D5ED598CD0E8F35AD49F3C3A17FDB7653E4E2DC4\ +A8D23CC34686EE4AD01F7407A7CD74429AC6D36DBF0CB6A3E302D0E5BDFCD048A3B90C1BE5AA8\ +E16C3D5884F9136B43FF7BB443764153D4AEC176C681B078F4CC53D6EB6AB76285537DDEE7C18\ +8C72441B52EDBDDBC77E02D34E513F2AABF92F44109CAFE8242BD0ECBAC5604A94B02EA44D43C\ +04E9476E6FBC48043916BFA1485C6093603600273C9C33F13114D78064AE42F3DC466C7DA543D\ +89C8D71 +AD534AFBED2FA39EE9F40E20FCF9E2C861024DB98DDCBA1CD118C49CA55EEBC20D6BA51B2271C\ +928B693D6A73F67FEB1B4571448588B46194617D25D910C6A9A130CC963155CF34079CB218A44\ +8A1F57E276D92A33386DDCA3D241DB78C8974ABD71DD05B0FA555709C9910D745185E6FE108E3\ +37F1907D0C56F8BFBF52B9704 % -E557905B56B13441574CAFCE2BD257A750B1A8B2C88D0E36\ +E18EF7C38DAC80D3948E17ED63AFF3B3467866E3B89D09A81B3D16B52F6A3C7134D3C6F5123E9\ +F617E3145BBFBE9AFD0D6E437EA4FF6F04BC67C4F1458B4F0F47B64 - 1C2BBBB19B74E86FD32\ +9E8DB6A8C3B1B9986D57ED5419C2E855F7D5469E35E76334BB42F4C43E3F3A31B9697C171DAC4\ +D97935A7E1A14AD209D6CF811F55C6DB83AA9E6DFECFCD6669DED7171EE22A40C6181615CAF3F\ +5296964 +EOF + if [ "0 +0" != "`cat tmp.bctest`" ]; then + failure=SCOtest + fi + fi + + + if [ "$failure" = none ]; then + # bc works; now check if it knows the 'print' command. + if [ "OK" = "`echo 'print \"OK\"' | $bc 2>/dev/null`" ] + then + echo "$bc" + else + echo "sed 's/print.*//' | $bc" + fi + exit 0 + fi + + echo "$bc does not work properly ('$failure' failed). Looking for another bc ..." >&2 + fi +done + +echo "No working bc found. Consider installing GNU bc." >&2 +echo "cat >/dev/null" +exit 1 diff --git a/lib/libc/gen/getprogname.3 b/lib/libc/gen/getprogname.3 new file mode 100644 index 000000000000..74225956f5d7 --- /dev/null +++ b/lib/libc/gen/getprogname.3 @@ -0,0 +1,92 @@ +.\" +.\" Copyright (c) 2001 Christopher G. Demetriou +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed for the +.\" NetBSD Project. See http://www.netbsd.org/ for +.\" information about NetBSD. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd May 1, 2001 +.Dt GETPROGNAME 3 +.Os +.Sh NAME +.Nm getprogname , +.Nm setprogname +.Nd get or set the program name +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.Fd #include <stdlib.h> +.Ft const char * +.Fn getprogname "void" +.Ft void +.Fn setprogname "const char *progname" +.Sh DESCRIPTION +The +.Fn getprogname +and +.Fn setprogname +functions manipulate the name of the current program. +They are used by error-reporting routines to produce +consistent output. +.Pp +The +.Fn getprogname +function returns the name of the program. +If the name has not been set yet, it will return +.Dv NULL . +.Pp +The +.Fn setprogname +function sets the name of the program. +Since a pointer to the given string is kept as the program name, +it should not be modified for the rest of the program's lifetime. +.Pp +In +.Fx , +the name of the program is set by the start-up code that is run before +.Fn main ; +thus, +running +.Fn setprogname +is not necessary. +Programs that desire maximum portability should still call it; +on another operating system, +these functions may be implemented in a portability library. +Calling +.Fn setprogname +allows the aforementioned library to learn the program name without +modifications to the start-up code. +.Sh SEE ALSO +.Xr err 3 , +.Xr setproctitle 3 +.Sh HISTORY +These functions first appeared in +.Nx 1.6 , +and made their way into +.Fx 5.0 . diff --git a/lib/libc/gen/getprogname.c b/lib/libc/gen/getprogname.c new file mode 100644 index 000000000000..54f721ab665c --- /dev/null +++ b/lib/libc/gen/getprogname.c @@ -0,0 +1,13 @@ +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = + "$FreeBSD$"; +#endif /* LIBC_RCS and not lint */ + +extern const char *__progname; + +const char * +getprogname(void) +{ + + return (__progname); +} diff --git a/lib/libc/gen/setprogname.c b/lib/libc/gen/setprogname.c new file mode 100644 index 000000000000..6c56013ef7c4 --- /dev/null +++ b/lib/libc/gen/setprogname.c @@ -0,0 +1,13 @@ +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = + "$FreeBSD$"; +#endif /* LIBC_RCS and not lint */ + +extern const char *__progname; + +void +setprogname(const char *progname) +{ + + __progname = progname; +} diff --git a/lib/libc/stdlib/hcreate.c b/lib/libc/stdlib/hcreate.c new file mode 100644 index 000000000000..ecc24310ae4b --- /dev/null +++ b/lib/libc/stdlib/hcreate.c @@ -0,0 +1,184 @@ +/* $NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $ */ +/* $FreeBSD$ */ + +/* + * Copyright (c) 2001 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the + * NetBSD Project. See http://www.netbsd.org/ for + * information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> + */ + +/* + * hcreate() / hsearch() / hdestroy() + * + * SysV/XPG4 hash table functions. + * + * Implementation done based on NetBSD manual page and Solaris manual page, + * plus my own personal experience about how they're supposed to work. + * + * I tried to look at Knuth (as cited by the Solaris manual page), but + * nobody had a copy in the office, so... + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <errno.h> +#include <search.h> +#include <stdlib.h> +#include <string.h> +#include "namespace.h" + +/* + * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit + * ptr machine) without adjusting MAX_BUCKETS_LG2 below. + */ +struct internal_entry { + SLIST_ENTRY(internal_entry) link; + ENTRY ent; +}; +SLIST_HEAD(internal_head, internal_entry); + +#define MIN_BUCKETS_LG2 4 +#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2) + +/* + * max * sizeof internal_entry must fit into size_t. + * assumes internal_entry is <= 32 (2^5) bytes. + */ +#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5) +#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2) + +/* Default hash function, from db/hash/hash_func.c */ +extern u_int32_t (*__default_hash)(const void *, size_t); + +static struct internal_head *htable; +static size_t htablesize; + +int +hcreate(size_t nel) +{ + size_t idx; + unsigned int p2; + + /* Make sure this this isn't called when a table already exists. */ + if (htable != NULL) { + errno = EINVAL; + return 0; + } + + /* If nel is too small, make it min sized. */ + if (nel < MIN_BUCKETS) + nel = MIN_BUCKETS; + + /* If it's too large, cap it. */ + if (nel > MAX_BUCKETS) + nel = MAX_BUCKETS; + + /* If it's is not a power of two in size, round up. */ + if ((nel & (nel - 1)) != 0) { + for (p2 = 0; nel != 0; p2++) + nel >>= 1; + nel = 1 << p2; + } + + /* Allocate the table. */ + htablesize = nel; + htable = malloc(htablesize * sizeof htable[0]); + if (htable == NULL) { + errno = ENOMEM; + return 0; + } + + /* Initialize it. */ + for (idx = 0; idx < htablesize; idx++) + SLIST_INIT(&htable[idx]); + + return 1; +} + +void +hdestroy(void) +{ + struct internal_entry *ie; + size_t idx; + + if (htable == NULL) + return; + + for (idx = 0; idx < htablesize; idx++) { + while (!SLIST_EMPTY(&htable[idx])) { + ie = SLIST_FIRST(&htable[idx]); + SLIST_REMOVE_HEAD(&htable[idx], link); + free(ie->ent.key); + free(ie); + } + } + free(htable); + htable = NULL; +} + +ENTRY * +hsearch(ENTRY item, ACTION action) +{ + struct internal_head *head; + struct internal_entry *ie; + uint32_t hashval; + size_t len; + + len = strlen(item.key); + hashval = (*__default_hash)(item.key, len); + + head = &htable[hashval & (htablesize - 1)]; + ie = SLIST_FIRST(head); + while (ie != NULL) { + if (strcmp(ie->ent.key, item.key) == 0) + break; + ie = SLIST_NEXT(ie, link); + } + + if (ie != NULL) + return &ie->ent; + else if (action == FIND) + return NULL; + + ie = malloc(sizeof *ie); + if (ie == NULL) + return NULL; + ie->ent.key = item.key; + ie->ent.data = item.data; + + SLIST_INSERT_HEAD(head, ie, link); + return &ie->ent; +} diff --git a/lib/libc/string/wmemchr.3 b/lib/libc/string/wmemchr.3 new file mode 100644 index 000000000000..ff82e73a3564 --- /dev/null +++ b/lib/libc/string/wmemchr.3 @@ -0,0 +1,145 @@ +.\" $NetBSD: wmemchr.3,v 1.4 2001/01/02 11:26:23 itojun Exp $ +.\" +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Chris Torek and the American National Standards Committee X3, +.\" on Information Processing Systems. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)strcpy.3 8.1 (Berkeley) 6/4/93 +.\" +.\" $FreeBSD$ +.\" +.Dd December 22, 2000 +.Dt WMEMCHR 3 +.Os +.Sh NAME +.Nm wmemchr , +.Nm wmemcmp , +.Nm wmemcpy , +.Nm wmemmove , +.Nm wmemset , +.Nm wcscat , +.Nm wcschr , +.Nm wcscmp , +.Nm wcscpy , +.Nm wcscspn , +.Nm wcslcat , +.Nm wcslcpy , +.Nm wcslen , +.Nm wcsncat , +.Nm wcsncmp , +.Nm wcsncpy , +.Nm wcspbrk , +.Nm wcsrchr , +.Nm wcsspn , +.Nm wcsstr +.Nd wide character string manipulation operations +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.Fd #include <wchar.h> +.Ft wchar_t * +.Fn wmemchr "const wchar_t *s" "wchar_t c" "size_t n" +.Ft int +.Fn wmemcmp "const wchar_t *s1" "const wchar_t *s2" "size_t n" +.Ft wchar_t * +.Fn wmemcpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n" +.Ft wchar_t * +.Fn wmemmove "wchar_t *s1" "const wchar_t *s2" "size_t n" +.Ft wchar_t * +.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n" +.Ft wchar_t * +.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2" +.Ft wchar_t * +.Fn wcschr "const wchar_t *s" "wchar_t c" +.Ft int +.Fn wcscmp "const wchar_t *s1" "const wchar_t *s2" +.Ft wchar_t * +.Fn wcscpy "wchar_t * restrict s1" "const wchar_t * restrict s2" +.Ft size_t +.Fn wcscspn "const wchar_t *s1" "const wchar_t *s2" +.Ft size_t +.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n" +.Ft size_t +.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n" +.Ft size_t +.Fn wcslen "const wchar_t *s" +.Ft wchar_t * +.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n" +.Ft int +.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n" +.Ft wchar_t * +.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n" +.Ft wchar_t * +.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2" +.Ft wchar_t * +.Fn wcsrchr "const wchar_t *s" "wchar_t c" +.Ft size_t +.Fn wcsspn "const wchar_t *s1" "const wchar_t *s2" +.Ft wchar_t * +.Fn wcsstr "const wchar_t *s1" "const wchar_t *s2" +.Sh DESCRIPTION +The functions implement string manipulation operations over wide character +strings. +For a detailed description, refer to documents for the respective single-byte +counterpart, such as +.Xr memchr 3 . +.Sh SEE ALSO +.Xr memchr 3 , +.Xr memcmp 3 , +.Xr memcpy 3 , +.Xr memmove 3 , +.Xr memset 3 , +.Xr strcat 3 , +.Xr strchr 3 , +.Xr strcmp 3 , +.Xr strcpy 3 , +.Xr strcspn 3 , +.Xr strlcat 3 , +.Xr strlcpy 3 , +.Xr strlen 3 , +.Xr strncat 3 , +.Xr strncmp 3 , +.Xr strncpy 3 , +.Xr strpbrk 3 , +.Xr strrchr 3 , +.Xr strspn 3 , +.Xr strstr 3 +.Sh STANDARDS +These functions conform to +.St -isoC-99 , +with the exception of +.Fn wcslcat +and +.Fn wcslcpy , +which are extensions. diff --git a/lib/libc_r/test/join_leak_d.c b/lib/libc_r/test/join_leak_d.c new file mode 100644 index 000000000000..6532ca5bfc74 --- /dev/null +++ b/lib/libc_r/test/join_leak_d.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + * Test for leaked joined threads. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <errno.h> +#include <string.h> +#include <pthread.h> + +#define NITERATIONS 16384 +#define MAXGROWTH 16384 + +void * +thread_entry(void *a_arg) +{ + return NULL; +} + +int +main(void) +{ + pthread_t thread; + int i, error; + char *brk, *nbrk; + unsigned growth; + + fprintf(stderr, "Test begin\n"); + + /* Get an initial brk value. */ + brk = sbrk(0); + + /* Create threads and join them, one at a time. */ + for (i = 0; i < NITERATIONS; i++) { + if ((error = pthread_create(&thread, NULL, thread_entry, NULL)) + != 0) { + fprintf(stderr, "Error in pthread_create(): %s\n", + strerror(error)); + exit(1); + } + if ((error = pthread_join(thread, NULL)) != 0) { + fprintf(stderr, "Error in pthread_join(): %s\n", + strerror(error)); + exit(1); + } + } + + /* Get a final brk value. */ + nbrk = sbrk(0); + + /* + * Check that the amount of heap space allocated is below an acceptable + * threshold. We could just compare brk and nbrk, but the test could + * conceivably break if the internals of the threads library changes. + */ + if (nbrk > brk) { + /* Heap grows up. */ + growth = nbrk - brk; + } else if (nbrk <= brk) { + /* Heap grows down, or no growth. */ + growth = brk - nbrk; + } + + if (growth > MAXGROWTH) { + fprintf(stderr, "Heap growth exceeded maximum (%u > %u)\n", + growth, MAXGROWTH); + } +#if (0) + else { + fprintf(stderr, "Heap growth acceptable (%u <= %u)\n", + growth, MAXGROWTH); + } +#endif + + fprintf(stderr, "Test end\n"); + return 0; +} diff --git a/lib/libc_r/test/join_leak_d.exp b/lib/libc_r/test/join_leak_d.exp new file mode 100644 index 000000000000..369a88dd2404 --- /dev/null +++ b/lib/libc_r/test/join_leak_d.exp @@ -0,0 +1,2 @@ +Test begin +Test end diff --git a/lib/libpam/modules/pam_krb5/COPYRIGHT b/lib/libpam/modules/pam_krb5/COPYRIGHT new file mode 100644 index 000000000000..42fb642c7230 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/COPYRIGHT @@ -0,0 +1,195 @@ +pam_krb5: + +$FreeBSD$ + +Copyright (c) Frank Cusack, 1999-2000. +fcusack@fcusack.com +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +ALTERNATIVELY, this product may be distributed under the terms of +the GNU Public License, in which case the provisions of the GPL are +required INSTEAD OF the above restrictions. (This clause is +necessary due to a potential bad interaction between the GPL and +the restrictions contained in a BSD-style copyright.) + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------- + +This software may contain code from Naomaru Itoi: + +PAM-kerberos5 module Copyright notice. +Naomaru Itoi <itoi@eecs.umich.edu>, June 24, 1997. + +---------------------------------------------------------------------------- +COPYRIGHT (c) 1997 +THE REGENTS OF THE UNIVERSITY OF MICHIGAN +ALL RIGHTS RESERVED + +PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS AND REDISTRIBUTE +THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR ANY PURPOSE, SO LONG AS THE NAME +OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY ADVERTISING OR PUBLICITY +PERTAINING TO THE USE OR DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, +WRITTEN PRIOR AUTHORIZATION. IF THE ABOVE COPYRIGHT NOTICE OR ANY OTHER +IDENTIFICATION OF THE UNIVERSITY OF MICHIGAN IS INCLUDED IN ANY COPY OF ANY +PORTION OF THIS SOFTWARE, THEN THE DISCLAIMER BELOW MUST ALSO BE INCLUDED. + +THE SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY OF +MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE +UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING +WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABITILY AND FITNESS FOR A +PARTICULAR PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE +LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN +CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +PAM-kerberos5 module is written based on PAM-kerberos4 module +by Derrick J. Brashear and kerberos5-1.0pl1 by M.I.T. kerberos team. +Permission to use, copy, modify, distribute this software is hereby +granted, as long as it is granted by Derrick J. Brashear and +M.I.T. kerberos team. Followings are their copyright information. +---------------------------------------------------------------------------- + +This software may contain code from Derrick J. Brashear: + + +Copyright (c) Derrick J. Brashear, 1996. All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +ALTERNATIVELY, this product may be distributed under the terms of +the GNU Public License, in which case the provisions of the GPL are +required INSTEAD OF the above restrictions. (This clause is +necessary due to a potential bad interaction between the GPL and +the restrictions contained in a BSD-style copyright.) + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------------- + +This software may contain code from MIT Kerberos 5: + +Copyright Notice and Legal Administrivia +---------------------------------------- + +Copyright (C) 1996 by the Massachusetts Institute of Technology. + +All rights reserved. + +Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of M.I.T. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. M.I.T. makes no representations about the suitability of +this software for any purpose. It is provided "as is" without express +or implied warranty. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +Individual source code files are copyright MIT, Cygnus Support, +OpenVision, Oracle, Sun Soft, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in kadmin/create, +kadmin/dbutil, kadmin/passwd, kadmin/server, lib/kadm5, and portions +of lib/rpc: + + Copyright, OpenVision Technologies, Inc., 1996, All Rights Reserved + + WARNING: Retrieving the OpenVision Kerberos Administration system + source code, as described below, indicates your acceptance of the + following terms. If you do not agree to the following terms, do not + retrieve the OpenVision Kerberos administration system. + + You may freely use and distribute the Source Code and Object Code + compiled from it, with or without modification, but this Source + Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, + INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR + FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER + EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY + FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, + WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE + CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY + OTHER REASON. + + OpenVision retains all copyrights in the donated Source Code. OpenVision + also retains copyright to derivative works of the Source Code, whether + created by OpenVision or by a third party. The OpenVision copyright + notice must be preserved if derivative works are made based on the + donated Source Code. + + OpenVision Technologies, Inc. has donated this Kerberos + Administration system to MIT for inclusion in the standard + Kerberos 5 distribution. This donation underscores our + commitment to continuing Kerberos technology development + and our gratitude for the valuable work which has been + performed by MIT and the Kerberos community. + + diff --git a/lib/libpam/modules/pam_krb5/README b/lib/libpam/modules/pam_krb5/README new file mode 100644 index 000000000000..ee97421bfa9d --- /dev/null +++ b/lib/libpam/modules/pam_krb5/README @@ -0,0 +1,72 @@ +$FreeBSD$ + +This is the README for pam_krb5, a PAM module which support Kerberos 5 +authentication. + +This software is Copyright (c) 1999-2000 Frank Cusack. +All Rights Reserved. + +See the COPYRIGHT file, included with this distribution, for copyright +and redistribution information. + +Author: +Frank Cusack +<fcusack@fcusack.com> + + +I. Kerberos notes + +This PAM module requires the MIT 1.1+ release of Kerberos, or the Cygnus +CNS distribution. It has not been tested against heimdal or any other +Kerberos distributions. + +Unlike other PAM Kerberos 5 modules out there, this one does not +use any private Kerberos interfaces. Thus, you need only the +header files and libraries that are part of the Kerberos distribution. + + +II. OS notes + +This software has been tested against Solaris 2.6. It should compile +against Linux (distributions?) with minimal (if any) changes. Reports +of OS [in]compatibilities are welcomed. + +dtlogin on Solaris doesn't support xrealm logins (probably a good thing). + +III. PAM notes/open issues + +auth module: +When is pam_sm_setcred() ever called with flags other than PAM_ESTABLISH_CRED +or PAM_DELETE_CRED? + +acct module: +I believe this to be complete. + +session module: +This is complete (both functions just return success). + +passwd module: +When is pam_sm_chauthtok() ever called with flags other than +PAM_UPDATE_AUTHTOK? + + +IV. Usage + +Simply change /etc/pam.conf to include this module. Make sure to include +the acct category whenever you use the auth category, or .k5login will +not get checked. + +You probably want to make this module "sufficient", before your unix +(or other) module(s). + + +V. Acknowledgements + +Thanks to Naomaru Itoi <itoi@eecs.umich.edu>, +Curtis King <curtis.king@cul.ca>, and Derrick Brashear <shadow@dementia.org>, +all of whom have written and made available Kerberos 4/5 modules. +Although no code in this module is directly from these author's modules, +(except the get_user_info() routine in support.c; derived from whichever +of these authors originally wrote the first module the other 2 copied from), +it was extremely helpful to look over their code which aided in my design. + diff --git a/lib/libpam/modules/pam_krb5/TODO b/lib/libpam/modules/pam_krb5/TODO new file mode 100644 index 000000000000..1f0939f256c8 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/TODO @@ -0,0 +1,16 @@ +$FreeBSD$ + +Things for 1.1, in no particular order: + +Check against Solaris 7, Solaris 8 beta. Check SEAM compatibility. +Check against Linux (Redhat, others?). +Check against HPUX. +Fix PAM flags checking. +Add more debugging for successful calls. +Move "entry" debugging up. +Check bounds on str* calls. [paranoia] + +Get defaults from krb5.conf? +** Allow no-xrealm, this module typically used for local login ** +** Add notes about runtime text relocation on Solaris ** + diff --git a/lib/libpam/modules/pam_krb5/compat_heimdal.c b/lib/libpam/modules/pam_krb5/compat_heimdal.c new file mode 100644 index 000000000000..fb4e1025e6ef --- /dev/null +++ b/lib/libpam/modules/pam_krb5/compat_heimdal.c @@ -0,0 +1,141 @@ +/* + * compat_heimdal.c + * + * Heimdal compatability layer. + * + * $FreeBSD$ + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <krb5.h> +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include "pam_krb5.h" + +const char * +compat_princ_component(krb5_context context, krb5_principal princ, int n) +{ + return princ->name.name_string.val[n]; +} + +void +compat_free_data_contents(krb5_context context, krb5_data *data) +{ + krb5_xfree(data->data); +} + +krb5_error_code +compat_cc_next_cred(krb5_context context, const krb5_ccache id, + krb5_cc_cursor *cursor, krb5_creds *creds) +{ + return krb5_cc_next_cred(context, id, creds, cursor); +} + + +static krb5_error_code +heimdal_pam_prompter(krb5_context context, void *data, const char *banner, int + num_prompts, krb5_prompt prompts[]) +{ + int pam_prompts = num_prompts; + int pamret, i; + + struct pam_message *msg; + struct pam_response *resp = NULL; + struct pam_conv *conv; + pam_handle_t *pamh = (pam_handle_t *) data; + + if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0) + return KRB5KRB_ERR_GENERIC; + + if (banner) + pam_prompts++; + + msg = calloc(sizeof(struct pam_message) * pam_prompts, 1); + if (!msg) + return ENOMEM; + + /* Now use pam_prompts as an index */ + pam_prompts = 0; + + if (banner) { + msg[pam_prompts].msg = malloc(strlen(banner) + 1); + if (!msg[pam_prompts].msg) + goto cleanup; + strcpy((char *) msg[pam_prompts].msg, banner); + msg[pam_prompts].msg_style = PAM_TEXT_INFO; + pam_prompts++; + } + + for (i = 0; i < num_prompts; i++) { + msg[pam_prompts].msg = malloc(strlen(prompts[i].prompt) + 3); + if (!msg[pam_prompts].msg) + goto cleanup; + sprintf((char *) msg[pam_prompts].msg, "%s: ", prompts[i].prompt); + msg[pam_prompts].msg_style = prompts[i].hidden ? PAM_PROMPT_ECHO_OFF + : PAM_PROMPT_ECHO_ON; + pam_prompts++; + } + + if ((pamret = conv->conv(pam_prompts, (const struct pam_message **) &msg, + &resp, conv->appdata_ptr)) != 0) + goto cleanup; + + if (!resp) + goto cleanup; + + /* Reuse pam_prompts as a starting index */ + pam_prompts = 0; + if (banner) + pam_prompts++; + + for (i = 0; i < num_prompts; i++, pam_prompts++) { + register int len; + if (!resp[pam_prompts].resp) { + pamret = PAM_AUTH_ERR; + goto cleanup; + } + len = strlen(resp[pam_prompts].resp); /* Help out the compiler */ + if (len > prompts[i].reply->length) { + pamret = PAM_AUTH_ERR; + goto cleanup; + } + memcpy(prompts[i].reply->data, resp[pam_prompts].resp, len); + prompts[i].reply->length = len; + } + +cleanup: + /* pam_prompts is correct at this point */ + + for (i = 0; i < pam_prompts; i++) { + if (msg[i].msg) + free((char *) msg[i].msg); + } + free(msg); + + if (resp) { + for (i = 0; i < pam_prompts; i++) { + /* + * Note that PAM is underspecified wrt free()'ing resp[i].resp. + * It's not clear if I should free it, or if the application + * has to. Therefore most (all?) apps won't free() it, and I + * can't either, as I am not sure it was malloc()'d. All PAM + * implementations I've seen leak memory here. Not so bad, IFF + * you fork/exec for each PAM authentication (as is typical). + */ +#if 0 + if (resp[i].resp) + free(resp[i].resp); +#endif /* 0 */ + } + /* This does not lose resp[i].resp if the application saved a copy. */ + free(resp); + } + + return (pamret ? KRB5KRB_ERR_GENERIC : 0); +} + +krb5_prompter_fct pam_prompter = heimdal_pam_prompter; diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.8 b/lib/libpam/modules/pam_krb5/pam_krb5.8 new file mode 100644 index 000000000000..7ef121170fb2 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5.8 @@ -0,0 +1,191 @@ +.\" +.\" $Id: pam_krb5.5,v 1.5 2000/01/05 00:59:56 fcusack Exp $ +.\" $FreeBSD$ +.TH pam_krb5 8 "15 Jan 1999" +.SH NAME +pam_krb5 \- Kerberos 5 PAM module +.SH SYNOPSIS +.LP +.B /usr/lib/pam_krb5.so +.LP +.SH DESCRIPTION +.IX "pam_krb5" "" "\fLpam_krb5\fP \(em Kerberos 5 PAM module" +.PP +The Kerberos 5 service module for PAM, typically +.BR /usr/lib/pam_krb5.so , +provides functionality for three PAM categories: +authentication, +account management, +and password management. +It also provides null functions for session management. +The +.B pam_krb5.so +module is a shared object +that can be dynamically loaded to provide +the necessary functionality upon demand. +Its path is specified in the +.SM PAM +configuration file. +.SH Kerberos 5 Authentication Module +The Kerberos 5 authentication component +provides functions to verify the identity of a user. +(\f3pam_sm_authenticate(\|)\f1) +and to set user specific credentials +(\f3pam_sm_setcred(\|)\f1). +.B pam_sm_authenticate(\|) +converts the supplied username into a Kerberos principal, +by appending the default local realm name. +It also supports usernames with explicit realm names. +If a realm name is supplied, then upon a sucessful return, it +changes the username by mapping the principal name into a local username +(calling \f3krb5_aname_to_localname()\f1). This typically just means +the realm name is stripped. +.LP +It prompts the user for a password and obtains a new Kerberos TGT for +the principal. The TGT is verified by obtaining a service +ticket for the local host. +.LP +When prompting for the current password, the authentication +module will use the prompt "Password for <principal>: ". +.LP +The +.B pam_sm_setcred(\|) +function stores the newly acquired credentials in a credentials cache, +and sets the environment variable +.B KRB5CCNAME +appropriately. +The credentials cache should be destroyed by the user at logout with +.BR kdestroy (1) . +.LP +The following options may be passed to the authentication module: +.TP 15 +.B debug +.BR syslog (3) +debugging information at +.SB LOG_DEBUG +level. +.TP +.B use_first_pass +If the authentication module is not the first in the stack, +and a previous module obtained the user's password, that password is +used to authenticate the user. If this fails, the authentication +module returns failure without prompting the user for a password. +This option has no effect if the authentication module is +the first in the stack, or if no previous modules obtained the +user's password. +.TP +.B try_first_pass +This option is similar to the +.B use_first_pass +option, except that if the previously obtained password fails, the +user is prompted for another password. +.TP +.B forwardable +Obtain forwardable Kerberos credentials for the user. +.TP +.B no_ccache +Do not save the obtained credentials in a credentials cache. This is a +useful option if the authentication module is used for services such +as ftp or pop, where the user would not be able to destroy them. [This +is not a recommendation to use the module for those services.] +.TP +.B ccache=<name> +Use <name> as the credentials cache. <name> must be in the form +.IR type:residual . +The special tokens +.BR %u , +to designate the decimal uid of the user; +and +.BR %p , +to designate the current process id; can be used in <name>. +.SH Kerberos 5 Account Management Module +The Kerberos 5 account management component +provides a function to perform account management, +.BR pam_sm_acct_mgmt(\|) . +The function verifies that the authenticated principal is allowed +to login to the local user account by calling +.B krb5_kuserok() +(which checks the user's \&.k5login file). +.SH Kerberos 5 Password Management Module +The Kerberos 5 password management component +provides a function to change passwords +(\f3pam_sm_chauthtok(\|)\f1). The username supplied (the +user running the +.BR passwd (1) +command, or the username given as an argument) is mapped into +a Kerberos principal name, using the same technique as in +the authentication module. Note that if a realm name was +explicitly supplied during authentication, but not during +a password change, the mapping +done by the password management module may not result in the +same principal as was used for authentication. +.LP +Unlike when +changing a unix password, the password management module will +allow any user to change any principal's password (if the user knows +the principal's old password, of course). Also unlike unix, root +is always prompted for the principal's old password. +.LP +The password management module uses the same heuristics as +.BR kpasswd (1) +to determine how to contact the Kerberos password server. +.LP +The following options may be passed to the password management +module: +.TP 15 +.B debug +.BR syslog (3) +debugging information at +.SB LOG_DEBUG +level. +.TP +.B use_first_pass +If the password management module is not the first in the stack, +and a previous module obtained the user's old password, that password is +used to authenticate the user. If this fails, the password +management +module returns failure without prompting the user for the old password. +If successful, the new password entered to the previous module is also +used as the new Kerberos password. If the new password fails, +the password management module returns failure without +prompting the user for a new password. +.TP +.B try_first_pass +This option is similar to the +.B use_first_pass +option, except that if the previously obtained old or new passwords fail, +the user is prompted for them. +.SH Kerberos 5 Session Management Module +The Kerberos 5 session management component +provides functions to initiate +(\f3pam_sm_open_session(\|)\f1) +and terminate +(\f3pam_sm_close_session(\|)\f1) +sessions. Since session management is not defined under Kerberos 5, +both of these functions simply return success. They are provided +only because of the naming conventions for PAM modules. +.SH ENVIRONMENT +.TP "\w'.SM KRB5CCNAME\ \ 'u" +.SM KRB5CCNAME +Location of the credentials cache. +.SH FILES +.TP "\w'/tmp/krb5cc_[uid]\ \ 'u" +/tmp/krb5cc_[uid] +default credentials cache ([uid] is the decimal UID of the user). +.TP +~/\&.k5login +file containing Kerberos principals that are allowed access. +.SH SEE ALSO +.BR kdestroy (1), +.BR passwd (1), +.BR pam (8), +.BR syslog (3), +.BR pam.conf (5). +.SH NOTES +Applications should not call +.B pam_authenticate() +more than once between calls to +.B pam_start() +and +.B pam_end() +when using the Kerberos 5 PAM module. diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.h b/lib/libpam/modules/pam_krb5/pam_krb5.h new file mode 100644 index 000000000000..ff0237321bdd --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5.h @@ -0,0 +1,23 @@ +/* + * pam_krb5.h + * + * $Id: pam_krb5.h,v 1.5 1999/01/19 23:43:10 fcusack Exp $ + * $FreeBSD$ + */ + +int get_user_info(pam_handle_t *, char *, int, char **); +int verify_krb_v5_tgt(krb5_context, krb5_ccache, char *, int); +void cleanup_cache(pam_handle_t *, void *, int); + +krb5_prompter_fct pam_prompter; + +const char *compat_princ_component(krb5_context, krb5_principal, int); +void compat_free_data_contents(krb5_context, krb5_data *); +krb5_error_code compat_cc_next_cred(krb5_context, const krb5_ccache, + krb5_cc_cursor *, krb5_creds *); + +#ifndef ENCTYPE_DES_CBC_MD5 +#define ENCTYPE_DES_CBC_MD5 ETYPE_DES_CBC_MD5 +#endif + + diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_acct.c b/lib/libpam/modules/pam_krb5/pam_krb5_acct.c new file mode 100644 index 000000000000..1a2910bc1d8e --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_acct.c @@ -0,0 +1,83 @@ +/* + * pam_krb5_acct.c + * + * PAM account management functions for pam_krb5 + * + * $FreeBSD$ + */ + +static const char rcsid[] = "$Id: pam_krb5_acct.c,v 1.3 1999/01/19 21:26:44 fcusack Exp $"; + +#include <syslog.h> /* syslog */ +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <krb5.h> +#include <com_err.h> +#include "pam_krb5.h" + +/* A useful logging macro */ +#define DLOG(error_func, error_msg) \ +if (debug) \ + syslog(LOG_DEBUG, "pam_krb5: pam_sm_acct_mgmt(%s %s): %s: %s", \ + service, name, error_func, error_msg) + +/* Check authorization of user */ +int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + krb5_error_code krbret; + krb5_context pam_context; + krb5_ccache ccache; + krb5_principal princ; + + char *service, *name; + int debug = 0; + int i, pamret; + + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) + debug = 1; + } + + /* Get username */ + if (pam_get_item(pamh, PAM_USER, (const void **) &name)) { + return PAM_PERM_DENIED;; + } + + /* Get service name */ + (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); + if (!service) + service = "unknown"; + + DLOG("entry", ""); + + if (pam_get_data(pamh, "ccache", (const void **) &ccache)) { + /* User did not use krb5 to login */ + DLOG("ccache", "not found"); + return PAM_SUCCESS; + } + + if ((krbret = krb5_init_context(&pam_context)) != 0) { + DLOG("krb5_init_context()", error_message(krbret)); + return PAM_PERM_DENIED;; + } + + if ((krbret = krb5_cc_get_principal(pam_context, ccache, &princ)) != 0) { + DLOG("krb5_cc_get_principal()", error_message(krbret)); + pamret = PAM_PERM_DENIED;; + goto cleanup; + } + + if (krb5_kuserok(pam_context, princ, name)) + pamret = PAM_SUCCESS; + else + pamret = PAM_PERM_DENIED; + krb5_free_principal(pam_context, princ); + +cleanup: + krb5_free_context(pam_context); + DLOG("exit", pamret ? "failure" : "success"); + return pamret; + +} + diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_auth.c b/lib/libpam/modules/pam_krb5/pam_krb5_auth.c new file mode 100644 index 000000000000..fd4270b7b3b2 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_auth.c @@ -0,0 +1,505 @@ +/* + * pam_krb5_auth.c + * + * PAM authentication management functions for pam_krb5 + * + * $FreeBSD$ + */ + +static const char rcsid[] = "$Id: pam_krb5_auth.c,v 1.18 2000/01/04 08:44:08 fcusack Exp $"; + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <limits.h> /* PATH_MAX */ +#include <pwd.h> /* getpwnam */ +#include <stdio.h> /* tmpnam */ +#include <stdlib.h> /* malloc */ +#include <strings.h> /* strchr */ +#include <syslog.h> /* syslog */ +#include <unistd.h> /* chown */ + +#include <security/pam_appl.h> +#include <security/pam_modules.h> + +#include <krb5.h> +#include <com_err.h> +#include "pam_krb5.h" + +extern krb5_cc_ops krb5_mcc_ops; + +/* A useful logging macro */ +#define DLOG(error_func, error_msg) \ +if (debug) \ + syslog(LOG_DEBUG, "pam_krb5: pam_sm_authenticate(%s %s): %s: %s", \ + service, name, error_func, error_msg) + +/* Authenticate a user via krb5 */ +int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + krb5_error_code krbret; + krb5_context pam_context; + krb5_creds creds; + krb5_principal princ; + krb5_ccache ccache, ccache_check; + krb5_get_init_creds_opt opts; + + int pamret, i; + const char *name; + char *source_princ = NULL; + char *princ_name = NULL; + char *pass = NULL, *service = NULL; + char *prompt = NULL; + char cache_name[L_tmpnam + 8]; + char lname[64]; /* local acct name */ + struct passwd *pw; + uid_t ruid; + + int debug = 0, try_first_pass = 0, use_first_pass = 0; + int forwardable = 0, reuse_ccache = 0, no_ccache = 0; + + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) + debug = 1; + else if (strcmp(argv[i], "try_first_pass") == 0) + try_first_pass = 1; + else if (strcmp(argv[i], "use_first_pass") == 0) + use_first_pass = 1; + else if (strcmp(argv[i], "forwardable") == 0) + forwardable = 1; + else if (strcmp(argv[i], "reuse_ccache") == 0) + reuse_ccache = 1; + else if (strcmp(argv[i], "no_ccache") == 0) + no_ccache = 1; + } + + /* Get username */ + if ((pamret = pam_get_user(pamh, &name, "login: ")) != PAM_SUCCESS) { + return PAM_SERVICE_ERR; + } + + /* Get service name */ + (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); + if (!service) + service = "unknown"; + + DLOG("entry", ""); + + if ((krbret = krb5_init_context(&pam_context)) != 0) { + DLOG("krb5_init_context()", error_message(krbret)); + return PAM_SERVICE_ERR; + } + krb5_get_init_creds_opt_init(&opts); + memset(&creds, 0, sizeof(krb5_creds)); + memset(cache_name, 0, sizeof(cache_name)); + memset(lname, 0, sizeof(lname)); + + if (forwardable) + krb5_get_init_creds_opt_set_forwardable(&opts, 1); + + /* For CNS */ + if ((krbret = krb5_cc_register(pam_context, &krb5_mcc_ops, FALSE)) != 0) { + /* Solaris dtlogin doesn't call pam_end() on failure */ + if (krbret != KRB5_CC_TYPE_EXISTS) { + DLOG("krb5_cc_register()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + } + + /* Get principal name */ + /* This case is for use mainly by su. + If non-root is authenticating as "root", use "source_user/root". */ + if (!strcmp(name, "root") && (ruid = getuid()) != 0) { + pw = getpwuid(ruid); + if (pw != NULL) + source_princ = (char *)malloc(strlen(pw->pw_name) + 6); + if (source_princ) + sprintf(source_princ, "%s/root", pw->pw_name); + } else { + source_princ = strdup(name); + } + if (!source_princ) { + DLOG("malloc()", "failure"); + pamret = PAM_BUF_ERR; + goto cleanup2; + } + + if ((krbret = krb5_parse_name(pam_context, source_princ, &princ)) != 0) { + DLOG("krb5_parse_name()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + + /* Now convert the principal name into something human readable */ + if ((krbret = krb5_unparse_name(pam_context, princ, &princ_name)) != 0) { + DLOG("krb5_unparse_name()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + + /* Get password */ + prompt = malloc(16 + strlen(princ_name)); + if (!prompt) { + DLOG("malloc()", "failure"); + pamret = PAM_BUF_ERR; + goto cleanup2; + } + (void) sprintf(prompt, "Password for %s: ", princ_name); + + if (try_first_pass || use_first_pass) + (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); + +get_pass: + if (!pass) { + try_first_pass = 0; + if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, + &pass)) != 0) { + DLOG("get_user_info()", pam_strerror(pamh, pamret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + /* We have to free pass. */ + if ((pamret = pam_set_item(pamh, PAM_AUTHTOK, pass)) != 0) { + DLOG("pam_set_item()", pam_strerror(pamh, pamret)); + free(pass); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + free(pass); + /* Now we get it back from the library. */ + (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); + } + + /* get a local account name for this principal */ + if ((krbret = krb5_aname_to_localname(pam_context, princ, + sizeof(lname), lname)) == 0) { + DLOG("changing PAM_USER to", lname); + if ((pamret = pam_set_item(pamh, PAM_USER, lname)) != 0) { + DLOG("pam_set_item()", pam_strerror(pamh, pamret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + if ((pamret = pam_get_item(pamh, PAM_USER, (const void **) &name) + != 0)) { + DLOG("pam_get_item()", pam_strerror(pamh, pamret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + } else { + DLOG("krb5_aname_to_localname()", error_message(krbret)); + /* Not an error. */ + } + + /* Verify the local user exists (AFTER getting the password) */ + pw = getpwnam(name); + if (!pw) { + DLOG("getpwnam()", lname); + pamret = PAM_USER_UNKNOWN; + goto cleanup2; + } + + /* Get a TGT */ + if ((krbret = krb5_get_init_creds_password(pam_context, &creds, princ, + pass, pam_prompter, pamh, 0, NULL, &opts)) != 0) { + DLOG("krb5_get_init_creds_password()", error_message(krbret)); + if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + pass = NULL; + goto get_pass; + } + pamret = PAM_AUTH_ERR; + goto cleanup2; + } + + /* Generate a unique cache_name */ + strcpy(cache_name, "MEMORY:"); + (void) tmpnam(&cache_name[7]); + + if ((krbret = krb5_cc_resolve(pam_context, cache_name, &ccache)) != 0) { + DLOG("krb5_cc_resolve()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup; + } + if ((krbret = krb5_cc_initialize(pam_context, ccache, princ)) != 0) { + DLOG("krb5_cc_initialize()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup; + } + if ((krbret = krb5_cc_store_cred(pam_context, ccache, &creds)) != 0) { + DLOG("krb5_cc_store_cred()", error_message(krbret)); + (void) krb5_cc_destroy(pam_context, ccache); + pamret = PAM_SERVICE_ERR; + goto cleanup; + } + + /* Verify it */ + if (verify_krb_v5_tgt(pam_context, ccache, service, debug) == -1) { + (void) krb5_cc_destroy(pam_context, ccache); + pamret = PAM_AUTH_ERR; + goto cleanup; + } + + /* A successful authentication, store ccache for sm_setcred() */ + if (!pam_get_data(pamh, "ccache", (const void **) &ccache_check)) { + DLOG("pam_get_data()", "ccache data already present"); + (void) krb5_cc_destroy(pam_context, ccache); + pamret = PAM_AUTH_ERR; + goto cleanup; + } + if ((pamret = pam_set_data(pamh, "ccache", ccache, cleanup_cache)) != 0) { + DLOG("pam_set_data()", pam_strerror(pamh, pamret)); + (void) krb5_cc_destroy(pam_context, ccache); + pamret = PAM_SERVICE_ERR; + goto cleanup; + } + +cleanup: + krb5_free_cred_contents(pam_context, &creds); +cleanup2: + krb5_free_principal(pam_context, princ); +cleanup3: + if (prompt) + free(prompt); + if (princ_name) + free(princ_name); + if (source_princ) + free(source_princ); + + krb5_free_context(pam_context); + DLOG("exit", pamret ? "failure" : "success"); + return pamret; +} + + + +/* redefine this for pam_sm_setcred() */ +#undef DLOG +#define DLOG(error_func, error_msg) \ +if (debug) \ + syslog(LOG_DEBUG, "pam_krb5: pam_sm_setcred(%s %s): %s: %s", \ + service, name, error_func, error_msg) + +/* Called after a successful authentication. Set user credentials. */ +int +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + + krb5_error_code krbret; + krb5_context pam_context; + krb5_principal princ; + krb5_creds creds; + krb5_ccache ccache_temp, ccache_perm; + krb5_cc_cursor cursor; + + int i, pamret; + char *name, *service = NULL; + char *cache_name = NULL, *cache_env_name; + struct passwd *pw = NULL; + + int debug = 0; + uid_t euid; + gid_t egid; + + if (flags == PAM_REINITIALIZE_CRED) + return PAM_SUCCESS; /* XXX Incorrect behavior */ + + if (flags != PAM_ESTABLISH_CRED && flags != PAM_DELETE_CRED) + return PAM_SERVICE_ERR; + + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) + debug = 1; + else if (strcmp(argv[i], "no_ccache") == 0) + return PAM_SUCCESS; + else if (strstr(argv[i], "ccache=") == argv[i]) + cache_name = (char *) &argv[i][7]; /* save for later */ + } + + /* Get username */ + if (pam_get_item(pamh, PAM_USER, (const void **) &name)) { + return PAM_SERVICE_ERR; + } + + /* Get service name */ + (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); + if (!service) + service = "unknown"; + + DLOG("entry", ""); + + if ((krbret = krb5_init_context(&pam_context)) != 0) { + DLOG("krb5_init_context()", error_message(krbret)); + return PAM_SERVICE_ERR; + } + + euid = geteuid(); /* Usually 0 */ + egid = getegid(); + + /* Retrieve the cache name */ + if ((pamret = pam_get_data(pamh, "ccache", (const void **) &ccache_temp)) + != 0) { + /* User did not use krb5 to login */ + DLOG("ccache", "not found"); + pamret = PAM_SUCCESS; + goto cleanup3; + } + + /* Get the uid. This should exist. */ + pw = getpwnam(name); + if (!pw) { + DLOG("getpwnam()", name); + pamret = PAM_USER_UNKNOWN; + goto cleanup3; + } + + /* Avoid following a symlink as root */ + if (setegid(pw->pw_gid)) { + DLOG("setegid()", name); /* XXX should really log group name or id */ + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + if (seteuid(pw->pw_uid)) { + DLOG("seteuid()", name); + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + + /* Get the cache name */ + if (!cache_name) { + cache_name = malloc(64); /* plenty big */ + if (!cache_name) { + DLOG("malloc()", "failure"); + pamret = PAM_BUF_ERR; + goto cleanup3; + } + sprintf(cache_name, "FILE:/tmp/krb5cc_%d", pw->pw_uid); + } else { + /* cache_name was supplied */ + char *p = calloc(PATH_MAX + 10, 1); /* should be plenty */ + char *q = cache_name; + if (!p) { + DLOG("malloc()", "failure"); + pamret = PAM_BUF_ERR; + goto cleanup3; + } + cache_name = p; + + /* convert %u and %p */ + while (*q) { + if (*q == '%') { + q++; + if (*q == 'u') { + sprintf(p, "%d", pw->pw_uid); + p += strlen(p); + } else if (*q == 'p') { + sprintf(p, "%d", getpid()); + p += strlen(p); + } else { + /* Not a special token */ + *p++ = '%'; + q--; + } + q++; + } else { + *p++ = *q++; + } + } + } + + if ((krbret = krb5_cc_resolve(pam_context, cache_name, &ccache_perm)) + != 0) { + DLOG("krb5_cc_resolve()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + if (flags == PAM_ESTABLISH_CRED) { + /* Initialize the new ccache */ + if ((krbret = krb5_cc_get_principal(pam_context, ccache_temp, &princ)) + != 0) { + DLOG("krb5_cc_get_principal()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup3; + } + if ((krbret = krb5_cc_initialize(pam_context, ccache_perm, princ)) != 0) { + DLOG("krb5_cc_initialize()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + + /* Prepare for iteration over creds */ + if ((krbret = krb5_cc_start_seq_get(pam_context, ccache_temp, &cursor)) + != 0) { + DLOG("krb5_cc_start_seq_get()", error_message(krbret)); + (void) krb5_cc_destroy(pam_context, ccache_perm); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + + /* Copy the creds (should be two of them) */ + while ((krbret = compat_cc_next_cred(pam_context, ccache_temp, + &cursor, &creds) == 0)) { + if ((krbret = krb5_cc_store_cred(pam_context, ccache_perm, + &creds)) != 0) { + DLOG("krb5_cc_store_cred()", error_message(krbret)); + (void) krb5_cc_destroy(pam_context, ccache_perm); + krb5_free_cred_contents(pam_context, &creds); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + krb5_free_cred_contents(pam_context, &creds); + } + (void) krb5_cc_end_seq_get(pam_context, ccache_temp, &cursor); + + if (strstr(cache_name, "FILE:") == cache_name) { + if (chown(&cache_name[5], pw->pw_uid, pw->pw_gid) == -1) { + DLOG("chown()", strerror(errno)); + (void) krb5_cc_destroy(pam_context, ccache_perm); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + if (chmod(&cache_name[5], (S_IRUSR|S_IWUSR)) == -1) { + DLOG("chmod()", strerror(errno)); + (void) krb5_cc_destroy(pam_context, ccache_perm); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + } + (void) krb5_cc_close(pam_context, ccache_perm); + + cache_env_name = malloc(strlen(cache_name) + 12); + if (!cache_env_name) { + DLOG("malloc()", "failure"); + (void) krb5_cc_destroy(pam_context, ccache_perm); + pamret = PAM_BUF_ERR; + goto cleanup2; + } + + sprintf(cache_env_name, "KRB5CCNAME=%s", cache_name); + if ((pamret = pam_putenv(pamh, cache_env_name)) != 0) { + DLOG("pam_putenv()", pam_strerror(pamh, pamret)); + (void) krb5_cc_destroy(pam_context, ccache_perm); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + } else { + /* flag == PAM_DELETE_CRED */ + if ((krbret = krb5_cc_destroy(pam_context, ccache_perm)) != 0) { + /* log error, but otherwise ignore it */ + DLOG("krb5_cc_destroy()", error_message(krbret)); + } + goto cleanup3; + } + +cleanup2: + krb5_free_principal(pam_context, princ); +cleanup3: + krb5_free_context(pam_context); + DLOG("exit", pamret ? "failure" : "success"); + (void) seteuid(euid); + (void) setegid(egid); + return pamret; +} + diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_pass.c b/lib/libpam/modules/pam_krb5/pam_krb5_pass.c new file mode 100644 index 000000000000..994c7f4720c6 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_pass.c @@ -0,0 +1,200 @@ +/* + * pam_krb5_pass.c + * + * PAM password management functions for pam_krb5 + * + * $FreeBSD$ + */ + +static const char rcsid[] = "$Id: pam_krb5_pass.c,v 1.3 1999/01/19 23:43:11 fcusack Exp $"; + +#include <errno.h> +#include <stdio.h> /* sprintf */ +#include <stdlib.h> /* malloc */ +#include <syslog.h> /* syslog */ +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <krb5.h> +#include <com_err.h> +#include "pam_krb5.h" + +/* A useful logging macro */ +#define DLOG(error_func, error_msg) \ +if (debug) \ + syslog(LOG_DEBUG, "pam_krb5: pam_sm_chauthtok(%s %s): %s: %s", \ + service, name, error_func, error_msg) + +/* Change a user's password */ +int +pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + krb5_error_code krbret; + krb5_context pam_context; + krb5_creds creds; + krb5_principal princ; + krb5_get_init_creds_opt opts; + + int result_code; + krb5_data result_code_string, result_string; + + int pamret, i; + char *name, *service = NULL, *pass = NULL, *pass2; + char *princ_name = NULL; + char *prompt = NULL; + + int debug = 0; + int try_first_pass = 0, use_first_pass = 0; + + if (!(flags & PAM_UPDATE_AUTHTOK)) + return PAM_AUTHTOK_ERR; + + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) + debug = 1; + else if (strcmp(argv[i], "try_first_pass") == 0) + try_first_pass = 1; + else if (strcmp(argv[i], "use_first_pass") == 0) + use_first_pass = 1; + } + + /* Get username */ + if ((pam_get_item(pamh, PAM_USER, (const void **) &name)) != 0) { + return PAM_SERVICE_ERR; + } + + /* Get service name */ + (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service); + if (!service) + service = "unknown"; + + DLOG("entry", ""); + + if ((krbret = krb5_init_context(&pam_context)) != 0) { + DLOG("krb5_init_context()", error_message(krbret)); + return PAM_SERVICE_ERR; + } + + if ((krbret = krb5_init_context(&pam_context)) != 0) { + DLOG("krb5_init_context()", error_message(krbret)); + return PAM_SERVICE_ERR; + } + krb5_get_init_creds_opt_init(&opts); + memset(&creds, 0, sizeof(krb5_creds)); + + /* Get principal name */ + if ((krbret = krb5_parse_name(pam_context, name, &princ)) != 0) { + DLOG("krb5_parse_name()", error_message(krbret)); + pamret = PAM_USER_UNKNOWN; + goto cleanup3; + } + + /* Now convert the principal name into something human readable */ + if ((krbret = krb5_unparse_name(pam_context, princ, &princ_name)) != 0) { + DLOG("krb5_unparse_name()", error_message(krbret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + + /* Get password */ + prompt = malloc(16 + strlen(princ_name)); + if (!prompt) { + DLOG("malloc()", "failure"); + pamret = PAM_BUF_ERR; + goto cleanup2; + } + (void) sprintf(prompt, "Password for %s: ", princ_name); + + if (try_first_pass || use_first_pass) + (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); + +get_pass: + if (!pass) { + try_first_pass = 0; + if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, + &pass)) != 0) { + DLOG("get_user_info()", pam_strerror(pamh, pamret)); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + /* We have to free pass. */ + if ((pamret = pam_set_item(pamh, PAM_AUTHTOK, pass)) != 0) { + DLOG("pam_set_item()", pam_strerror(pamh, pamret)); + free(pass); + pamret = PAM_SERVICE_ERR; + goto cleanup2; + } + free(pass); + /* Now we get it back from the library. */ + (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass); + } + + if ((krbret = krb5_get_init_creds_password(pam_context, &creds, princ, + pass, pam_prompter, pamh, 0, "kadmin/changepw", &opts)) != 0) { + DLOG("krb5_get_init_creds_password()", error_message(krbret)); + if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + pass = NULL; + goto get_pass; + } + pamret = PAM_AUTH_ERR; + goto cleanup2; + } + + /* Now get the new password */ + free(prompt); + prompt = "Enter new password: "; + if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass)) + != 0) { + DLOG("get_user_info()", pam_strerror(pamh, pamret)); + prompt = NULL; + pamret = PAM_SERVICE_ERR; + goto cleanup; + } + prompt = "Enter it again: "; + if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass2)) + != 0) { + DLOG("get_user_info()", pam_strerror(pamh, pamret)); + prompt = NULL; + pamret = PAM_SERVICE_ERR; + goto cleanup; + } + prompt = NULL; + + if (strcmp(pass, pass2) != 0) { + DLOG("strcmp()", "passwords not equal"); + pamret = PAM_AUTHTOK_ERR; + goto cleanup; + } + + /* Change it */ + if ((krbret = krb5_change_password(pam_context, &creds, pass, + &result_code, &result_code_string, &result_string)) != 0) { + DLOG("krb5_change_password()", error_message(krbret)); + pamret = PAM_AUTHTOK_ERR; + goto cleanup; + } + if (result_code) { + DLOG("krb5_change_password() (result_code)", ""); + pamret = PAM_AUTHTOK_ERR; + goto cleanup; + } + + if (result_string.data) + free(result_string.data); + if (result_code_string.data) + free(result_code_string.data); + +cleanup: + krb5_free_cred_contents(pam_context, &creds); +cleanup2: + krb5_free_principal(pam_context, princ); +cleanup3: + if (prompt) + free(prompt); + if (princ_name) + free(princ_name); + + krb5_free_context(pam_context); + DLOG("exit", pamret ? "failure" : "success"); + return pamret; +} + diff --git a/lib/libpam/modules/pam_krb5/pam_krb5_sess.c b/lib/libpam/modules/pam_krb5/pam_krb5_sess.c new file mode 100644 index 000000000000..b2df06434fa6 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam_krb5_sess.c @@ -0,0 +1,28 @@ +/* + * pam_krb5_sess.c + * + * PAM session management functions for pam_krb5 + * (null functions) + * + * $FreeBSD$ + */ + +static const char rcsid[] = "$Id: pam_krb5_sess.c,v 1.3 1999/01/19 20:49:44 fcusack Exp $"; + +#include <security/pam_appl.h> +#include <security/pam_modules.h> + +/* Initiate session management */ +int +pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + + +/* Terminate session management */ +int +pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} diff --git a/lib/libpam/modules/pam_krb5/support.c b/lib/libpam/modules/pam_krb5/support.c new file mode 100644 index 000000000000..8e1aecda640f --- /dev/null +++ b/lib/libpam/modules/pam_krb5/support.c @@ -0,0 +1,185 @@ +/* + * support.c + * + * Support functions for pam_krb5 + * + * $FreeBSD$ + */ + +static const char rcsid[] = "$Id: support.c,v 1.8 2000/01/04 09:50:03 fcusack Exp $"; + +#include <errno.h> +#include <stdio.h> /* BUFSIZ */ +#include <stdlib.h> /* malloc */ +#include <string.h> /* strncpy */ +#include <syslog.h> /* syslog */ +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <krb5.h> +#include <com_err.h> +#include "pam_krb5.h" + +/* + * Get info from the user. Disallow null responses (regardless of flags). + * response gets allocated and filled in on successful return. Caller + * is responsible for freeing it. + */ +int +get_user_info(pam_handle_t *pamh, char *prompt, int type, char **response) +{ + int pamret; + struct pam_message msg; + const struct pam_message *pmsg; + struct pam_response *resp = NULL; + struct pam_conv *conv; + + if ((pamret = pam_get_item(pamh, PAM_CONV, (const void **) &conv)) != 0) + return pamret; + + /* set up conversation call */ + pmsg = &msg; + msg.msg_style = type; + msg.msg = prompt; + + if ((pamret = conv->conv(1, &pmsg, &resp, conv->appdata_ptr)) != 0) + return pamret; + + /* Caller should ignore errors for non-response conversations */ + if (!resp) + return PAM_CONV_ERR; + + if (!(resp->resp && resp->resp[0])) { + free(resp); + return PAM_AUTH_ERR; + } + + *response = resp->resp; + free(resp); + return pamret; +} + +/* + * This routine with some modification is from the MIT V5B6 appl/bsd/login.c + * Modified by Sam Hartman <hartmans@mit.edu> to support PAM services + * for Debian. + * + * Verify the Kerberos ticket-granting ticket just retrieved for the + * user. If the Kerberos server doesn't respond, assume the user is + * trying to fake us out (since we DID just get a TGT from what is + * supposedly our KDC). If the host/<host> service is unknown (i.e., + * the local keytab doesn't have it), and we cannot find another + * service we do have, let her in. + * + * Returns 1 for confirmation, -1 for failure, 0 for uncertainty. + */ +int +verify_krb_v5_tgt(krb5_context context, krb5_ccache ccache, + char * pam_service, int debug) +{ + char phost[BUFSIZ]; + char *services [3]; + char **service; + krb5_error_code retval = -1; + krb5_principal princ; + krb5_keyblock * keyblock = 0; + krb5_data packet; + krb5_auth_context auth_context = NULL; + + packet.data = 0; + + /* + * If possible we want to try and verify the ticket we have + * received against a keytab. We will try multiple service + * principals, including at least the host principal and the PAM + * service principal. The host principal is preferred because access + * to that key is generally sufficient to compromise root, while the + * service key for this PAM service may be less carefully guarded. + * It is important to check the keytab first before the KDC so we do + * not get spoofed by a fake KDC.*/ + services [0] = "host"; + services [1] = pam_service; + services [2] = NULL; + for ( service = &services[0]; *service != NULL; service++ ) { + if ((retval = krb5_sname_to_principal(context, NULL, *service, KRB5_NT_SRV_HST, + &princ)) != 0) { + if (debug) + syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", + "krb5_sname_to_principal()", error_message(retval)); + return -1; + } + + /* Extract the name directly. */ + strncpy(phost, compat_princ_component(context, princ, 1), BUFSIZ); + phost[BUFSIZ - 1] = '\0'; + + /* + * Do we have service/<host> keys? + * (use default/configured keytab, kvno IGNORE_VNO to get the + * first match, and ignore enctype.) + */ + if ((retval = krb5_kt_read_service_key(context, NULL, princ, 0, + 0, &keyblock)) != 0) + continue; + break; + } + if (retval != 0 ) { /* failed to find key */ + /* Keytab or service key does not exist */ + if (debug) + syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", + "krb5_kt_read_service_key()", error_message(retval)); + retval = 0; + goto cleanup; + } + if (keyblock) + krb5_free_keyblock(context, keyblock); + + /* Talk to the kdc and construct the ticket. */ + retval = krb5_mk_req(context, &auth_context, 0, *service, phost, + NULL, ccache, &packet); + if (auth_context) { + krb5_auth_con_free(context, auth_context); + auth_context = NULL; /* setup for rd_req */ + } + if (retval) { + if (debug) + syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", + "krb5_mk_req()", error_message(retval)); + retval = -1; + goto cleanup; + } + + /* Try to use the ticket. */ + retval = krb5_rd_req(context, &auth_context, &packet, princ, + NULL, NULL, NULL); + if (retval) { + if (debug) + syslog(LOG_DEBUG, "pam_krb5: verify_krb_v5_tgt(): %s: %s", + "krb5_rd_req()", error_message(retval)); + retval = -1; + } else { + retval = 1; + } + +cleanup: + if (packet.data) + compat_free_data_contents(context, &packet); + krb5_free_principal(context, princ); + return retval; + +} + + +/* Free the memory for cache_name. Called by pam_end() */ +void +cleanup_cache(pam_handle_t *pamh, void *data, int pam_end_status) +{ + krb5_context pam_context; + krb5_ccache ccache; + + if (krb5_init_context(&pam_context)) + return; + + ccache = (krb5_ccache) data; + (void) krb5_cc_destroy(pam_context, ccache); + krb5_free_context(pam_context); +} diff --git a/release/doc/share/sgml/release.dsl b/release/doc/share/sgml/release.dsl new file mode 100644 index 000000000000..531a3f5363f3 --- /dev/null +++ b/release/doc/share/sgml/release.dsl @@ -0,0 +1,38 @@ +<!-- $FreeBSD$ --> + +<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [ +<!ENTITY freebsd.dsl PUBLIC "-//FreeBSD//DOCUMENT DocBook Stylesheet//EN" CDATA DSSSL> +]> + +<style-sheet> + <style-specification use="docbook"> + <style-specification-body> + +; The architecture we're building for. We need to define this as a +; procedure, because we may not be able to evaluate it until we are +; at a point in formatting where (current-node) is defined. + +(default + (let* ((arch (attribute-string (normalize "arch"))) + (for-arch (entity-text "arch"))) + (if (or (equal? arch #f) + (equal? arch "")) + (next-match) +; We can do a lot more flexible things here. Like it'd be nice to +; tokenize the arch= attribute and do comparisons of for-arch against +; different substrings. + (cond ((equal? arch for-arch) (next-match)) + (else (empty-sosofo)))))) + +; We might have some sect1 level elements where the modification times +; are significant. An example of this is the "What's New" section in +; the release notes. We enable the printing of pubdate entry in +; sect1info elements to support this. +(element (sect1info pubdate) (process-children)) + + </style-specification-body> + </style-specification> + + <external-specification id="docbook" document="freebsd.dsl"> +</style-sheet> + diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk new file mode 100644 index 000000000000..566917c4b976 --- /dev/null +++ b/share/mk/bsd.sys.mk @@ -0,0 +1,39 @@ +# $FreeBSD$ +# +# This file contains common settings used for building FreeBSD +# sources. + +# Enable various levels of compiler warning checks. These may be +# overridden (e.g. if using a non-gcc compiler) by defining NO_WARNS. + +.if !defined(NO_WARNS) +. if defined(WARNS) +. if ${WARNS} > 0 +CFLAGS += -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith +# XXX Delete -Wuninitialized by default for now -- the compiler doesn't +# XXX always get it right. +CFLAGS += -Wno-uninitialized +. if !defined(NO_WERROR) +CFLAGS += -Werror +. endif +. endif +. if ${WARNS} > 1 +CFLAGS += -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow +. endif +. endif + +. if defined(FORMAT_AUDIT) +WFORMAT = 1 +. endif +. if defined(WFORMAT) +. if ${WFORMAT} > 0 +CFLAGS += -Wnon-const-format -Wno-format-extra-args +. if !defined(NO_WERROR) +CFLAGS += -Werror +. endif +. endif +. endif +.endif + +# Allow user-specified additional warning flags +CFLAGS += ${CWARNFLAGS} diff --git a/share/monetdef/sk_SK.ISO8859-2.src b/share/monetdef/sk_SK.ISO8859-2.src new file mode 100644 index 000000000000..dc2ac34f5564 --- /dev/null +++ b/share/monetdef/sk_SK.ISO8859-2.src @@ -0,0 +1,38 @@ +# $FreeBSD$ +# +# Slovak monetary definition by Juraj Bednar <juraj@bednar.sk> +# +# WARNING: spaces may be essential at the end of lines +# WARNING: empty lines are essential too +# +# int_curr_symbol (last character always SPACE) +SKK +# currency_symbol +Sk +# mon_decimal_point +, +# mon_thousands_sep + +# mon_grouping +3;3 +# positive_sign + +# negative_sign +- +# int_frac_digits +2 +# frac_digits +2 +# p_cs_precedes +1 +# p_sep_by_space +2 +# n_cs_precedes +1 +# n_sep_by_space +2 +# p_sign_posn +4 +# n_sign_posn +4 +# EOF diff --git a/share/numericdef/sk_SK.ISO8859-2.src b/share/numericdef/sk_SK.ISO8859-2.src new file mode 100644 index 000000000000..19776246f8ca --- /dev/null +++ b/share/numericdef/sk_SK.ISO8859-2.src @@ -0,0 +1,14 @@ +# $FreeBSD$ +# +# Slovak numeric definition +# +# WARNING: spaces may be essential at the end of lines +# WARNING: empty lines are essential too +# +# decimal_point +, +# thousands_sep + +# grouping +3;3 +# EOF diff --git a/share/timedef/sk_SK.ISO8859-2.src b/share/timedef/sk_SK.ISO8859-2.src new file mode 100644 index 000000000000..a10c861f4dd6 --- /dev/null +++ b/share/timedef/sk_SK.ISO8859-2.src @@ -0,0 +1,105 @@ +# Slovak month and day names +# by Juraj Bednar <juraj@bednar.sk> +# +# $FreeBSD$ +# +# WARNING: spaces may be essential at the end of lines +# WARNING: empty lines are essential too +# +# Short months names +# +jan +feb +mar +apr +máj +jún +júl +aug +sep +okt +nov +dec +# +# Long months names +# +január +február +marec +apríl +máj +jún +júl +august +september +október +november +december +# +# Short weekdays names +# +ne +po +ut +st +¹t +pi +so +# +# Long weekdays names +# +nedeµa +pondelok +utorok +streda +¹tvrtok +piatok +sobota +# +# X_fmt +# +%H:%M:%S +# +# x_fmt +# +%d.%m.%Y +# +# c_fmt +# +%a %e %b %X %Y +# +# am +# + +# +# pm +# + +# +# date_fmt +# +%a %e. %B %Y %X %Z +# +# Long month names in alternative form +# +január +február +marec +apríl +máj +jún +júl +august +september +október +november +december +# +# md_order +# +dm +# +# ampm_fmt +# + +# EOF diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c new file mode 100644 index 000000000000..b5196c016854 --- /dev/null +++ b/sys/fs/smbfs/smbfs_vfsops.c @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2000-2001, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_netsmb.h" +#ifndef NETSMB +#error "SMBFS requires option NETSMB" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/vnode.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/malloc.h> + + +#include <netsmb/smb.h> +#include <netsmb/smb_conn.h> +#include <netsmb/smb_subr.h> +#include <netsmb/smb_dev.h> + +#include <fs/smbfs/smbfs.h> +#include <fs/smbfs/smbfs_node.h> +#include <fs/smbfs/smbfs_subr.h> + +int smbfs_debuglevel = 0; + +static int smbfs_version = SMBFS_VERSION; + +#ifdef SMBFS_USEZONE +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_zone.h> + +vm_zone_t smbfsmount_zone; +#endif + +SYSCTL_NODE(_vfs, OID_AUTO, smbfs, CTLFLAG_RW, 0, "SMB/CIFS file system"); +SYSCTL_INT(_vfs_smbfs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, ""); +SYSCTL_INT(_vfs_smbfs, OID_AUTO, debuglevel, CTLFLAG_RW, &smbfs_debuglevel, 0, ""); + +static MALLOC_DEFINE(M_SMBFSHASH, "SMBFS hash", "SMBFS hash table"); + + +static int smbfs_mount(struct mount *, char *, caddr_t, + struct nameidata *, struct proc *); +static int smbfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); +static int smbfs_root(struct mount *, struct vnode **); +static int smbfs_start(struct mount *, int, struct proc *); +static int smbfs_statfs(struct mount *, struct statfs *, struct proc *); +static int smbfs_sync(struct mount *, int, struct ucred *, struct proc *); +static int smbfs_unmount(struct mount *, int, struct proc *); +static int smbfs_init(struct vfsconf *vfsp); +static int smbfs_uninit(struct vfsconf *vfsp); + +#if __FreeBSD_version < 400009 +static int smbfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp); +static int smbfs_fhtovp(struct mount *, struct fid *, + struct sockaddr *, struct vnode **, int *, + struct ucred **); +static int smbfs_vptofh(struct vnode *, struct fid *); +#endif + +static struct vfsops smbfs_vfsops = { + smbfs_mount, + smbfs_start, + smbfs_unmount, + smbfs_root, + smbfs_quotactl, + smbfs_statfs, + smbfs_sync, +#if __FreeBSD_version > 400008 + vfs_stdvget, + vfs_stdfhtovp, /* shouldn't happen */ + vfs_stdcheckexp, + vfs_stdvptofh, /* shouldn't happen */ +#else + smbfs_vget, + smbfs_fhtovp, + smbfs_vptofh, +#endif + smbfs_init, + smbfs_uninit, +#ifndef FB_RELENG3 + vfs_stdextattrctl, +#else +#define M_USE_RESERVE M_KERNEL + &sysctl___vfs_smbfs +#endif +}; + + +VFS_SET(smbfs_vfsops, smbfs, VFCF_NETWORK); + +MODULE_DEPEND(smbfs, netsmb, NSMB_VERSION, NSMB_VERSION, NSMB_VERSION); +MODULE_DEPEND(smbfs, libiconv, 1, 1, 1); + +int smbfs_pbuf_freecnt = -1; /* start out unlimited */ + +static int +smbfs_mount(struct mount *mp, char *path, caddr_t data, + struct nameidata *ndp, struct proc *p) +{ + struct smbfs_args args; /* will hold data from mount request */ + struct smbmount *smp = NULL; + struct smb_vc *vcp; + struct smb_share *ssp = NULL; + struct vnode *vp; + struct smb_cred scred; +#ifndef FB_CURRENT + size_t size; +#endif + int error; + char *pc, *pe; + + if (data == NULL) { + printf("missing data argument\n"); + return EINVAL; + } + if (mp->mnt_flag & MNT_UPDATE) { + printf("MNT_UPDATE not implemented"); + return EOPNOTSUPP; + } + error = copyin(data, (caddr_t)&args, sizeof(struct smbfs_args)); + if (error) + return error; + if (args.version != SMBFS_VERSION) { + printf("mount version mismatch: kernel=%d, mount=%d\n", + SMBFS_VERSION, args.version); + return EINVAL; + } + smb_makescred(&scred, p, p->p_ucred); + error = smb_dev2share(args.dev, SMBM_EXEC, &scred, &ssp); + if (error) { + printf("invalid device handle %d (%d)\n", args.dev, error); + return error; + } + vcp = SSTOVC(ssp); + smb_share_unlock(ssp, 0, p); + mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax; + +#ifdef SMBFS_USEZONE + smp = zalloc(smbfsmount_zone); +#else + MALLOC(smp, struct smbmount*, sizeof(*smp), M_SMBFSDATA, M_USE_RESERVE); +#endif + if (smp == NULL) { + printf("could not alloc smbmount\n"); + error = ENOMEM; + goto bad; + } + bzero(smp, sizeof(*smp)); + mp->mnt_data = (qaddr_t)smp; + smp->sm_hash = hashinit(desiredvnodes, M_SMBFSHASH, &smp->sm_hashlen); + if (smp->sm_hash == NULL) + goto bad; + lockinit(&smp->sm_hashlock, PVFS, "smbfsh", 0, 0); + smp->sm_share = ssp; + smp->sm_root = NULL; + smp->sm_args = args; + smp->sm_caseopt = args.caseopt; + smp->sm_args.file_mode = (smp->sm_args.file_mode & + (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; + smp->sm_args.dir_mode = (smp->sm_args.dir_mode & + (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; + +/* simple_lock_init(&smp->sm_npslock);*/ +#ifndef FB_CURRENT + error = copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); + if (error) + goto bad; + bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); +#endif + pc = mp->mnt_stat.f_mntfromname; + pe = pc + sizeof(mp->mnt_stat.f_mntfromname); + bzero(pc, MNAMELEN); + *pc++ = '/'; + *pc++ = '/'; + pc=index(strncpy(pc, vcp->vc_username, pe - pc - 2), 0); + if (pc < pe-1) { + *(pc++) = '@'; + pc = index(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0); + if (pc < pe - 1) { + *(pc++) = '/'; + strncpy(pc, ssp->ss_name, pe - pc - 2); + } + } + /* protect against invalid mount points */ + smp->sm_args.mount_point[sizeof(smp->sm_args.mount_point) - 1] = '\0'; + vfs_getnewfsid(mp); + error = smbfs_root(mp, &vp); + if (error) + goto bad; + VOP_UNLOCK(vp, 0, p); + SMBVDEBUG("root.v_usecount = %d\n", vp->v_usecount); + +#ifdef DIAGNOSTICS + SMBERROR("mp=%p\n", mp); +#endif + return error; +bad: + if (smp) { + if (smp->sm_hash) + free(smp->sm_hash, M_SMBFSHASH); + lockdestroy(&smp->sm_hashlock); +#ifdef SMBFS_USEZONE + zfree(smbfsmount_zone, smp); +#else + free(smp, M_SMBFSDATA); +#endif + } + if (ssp) + smb_share_put(ssp, &scred); + return error; +} + +/* Unmount the filesystem described by mp. */ +static int +smbfs_unmount(struct mount *mp, int mntflags, struct proc *p) +{ + struct smbmount *smp = VFSTOSMBFS(mp); + struct smb_cred scred; + int error, flags; + + SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags); + flags = 0; + if (mntflags & MNT_FORCE) + flags |= FORCECLOSE; + /* There is 1 extra root vnode reference from smbfs_mount(). */ + error = vflush(mp, 1, flags); + if (error) + return error; + smb_makescred(&scred, p, p->p_ucred); + smb_share_put(smp->sm_share, &scred); + mp->mnt_data = (qaddr_t)0; + + if (smp->sm_hash) + free(smp->sm_hash, M_SMBFSHASH); + lockdestroy(&smp->sm_hashlock); +#ifdef SMBFS_USEZONE + zfree(smbfsmount_zone, smp); +#else + free(smp, M_SMBFSDATA); +#endif + mp->mnt_flag &= ~MNT_LOCAL; + return error; +} + +/* + * Return locked root vnode of a filesystem + */ +static int +smbfs_root(struct mount *mp, struct vnode **vpp) +{ + struct smbmount *smp = VFSTOSMBFS(mp); + struct vnode *vp; + struct smbnode *np; + struct smbfattr fattr; + struct proc *p = curproc; + struct ucred *cred = p->p_ucred; + struct smb_cred scred; + int error; + + if (smp == NULL) { + SMBERROR("smp == NULL (bug in umount)\n"); + return EINVAL; + } + if (smp->sm_root) { + *vpp = SMBTOV(smp->sm_root); + return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, p); + } + smb_makescred(&scred, p, cred); + error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred); + if (error) + return error; + error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp); + if (error) + return error; + vp->v_flag |= VROOT; + np = VTOSMB(vp); + smp->sm_root = np; + *vpp = vp; + return 0; +} + +/* + * Vfs start routine, a no-op. + */ +/* ARGSUSED */ +static int +smbfs_start(mp, flags, p) + struct mount *mp; + int flags; + struct proc *p; +{ + SMBVDEBUG("flags=%04x\n", flags); + return 0; +} + +/* + * Do operations associated with quotas, not supported + */ +/* ARGSUSED */ +static int +smbfs_quotactl(mp, cmd, uid, arg, p) + struct mount *mp; + int cmd; + uid_t uid; + caddr_t arg; + struct proc *p; +{ + SMBVDEBUG("return EOPNOTSUPP\n"); + return EOPNOTSUPP; +} + +/*ARGSUSED*/ +int +smbfs_init(struct vfsconf *vfsp) +{ +#ifndef SMP + int name[2]; + int olen, ncpu, plen, error; + + name[0] = CTL_HW; + name[1] = HW_NCPU; + error = kernel_sysctl(curproc, name, 2, &ncpu, &olen, NULL, 0, &plen); + if (error == 0 && ncpu > 1) + printf("warning: smbfs module compiled without SMP support."); +#endif + +#ifdef SMBFS_USEZONE + smbfsmount_zone = zinit("SMBFSMOUNT", sizeof(struct smbmount), 0, 0, 1); +#endif + smbfs_pbuf_freecnt = nswbuf / 2 + 1; + SMBVDEBUG("done.\n"); + return 0; +} + +/*ARGSUSED*/ +int +smbfs_uninit(struct vfsconf *vfsp) +{ + + SMBVDEBUG("done.\n"); + return 0; +} + +/* + * smbfs_statfs call + */ +int +smbfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) +{ + struct smbmount *smp = VFSTOSMBFS(mp); + struct smbnode *np = smp->sm_root; + struct smb_share *ssp = smp->sm_share; + struct smb_cred scred; + int error = 0; + + if (np == NULL) + return EINVAL; + + sbp->f_iosize = SSTOVC(ssp)->vc_txmax; /* optimal transfer block size */ + sbp->f_spare2 = 0; /* placeholder */ + smb_makescred(&scred, p, p->p_ucred); + + if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) + error = smbfs_smb_statfs2(ssp, sbp, &scred); + else + error = smbfs_smb_statfs(ssp, sbp, &scred); + if (error) + return error; + sbp->f_flags = 0; /* copy of mount exported flags */ + if (sbp != &mp->mnt_stat) { + sbp->f_fsid = mp->mnt_stat.f_fsid; /* file system id */ + sbp->f_owner = mp->mnt_stat.f_owner; /* user that mounted the filesystem */ + sbp->f_type = mp->mnt_vfc->vfc_typenum; /* type of filesystem */ + bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); + bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); + } + strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN); + return 0; +} + +/* + * Flush out the buffer cache + */ +/* ARGSUSED */ +static int +smbfs_sync(mp, waitfor, cred, p) + struct mount *mp; + int waitfor; + struct ucred *cred; + struct proc *p; +{ + struct vnode *vp; + int error, allerror = 0; + /* + * Force stale buffer cache information to be flushed. + */ +loop: + for (vp = mp->mnt_vnodelist.lh_first; + vp != NULL; + vp = vp->v_mntvnodes.le_next) { + /* + * If the vnode that we are about to sync is no longer + * associated with this mount point, start over. + */ + if (vp->v_mount != mp) + goto loop; +#ifndef FB_RELENG3 + if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || +#else + if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || +#endif + waitfor == MNT_LAZY) + continue; + if (vget(vp, LK_EXCLUSIVE, p)) + goto loop; + error = VOP_FSYNC(vp, cred, waitfor, p); + if (error) + allerror = error; + vput(vp); + } + return (allerror); +} + +#if __FreeBSD_version < 400009 +/* + * smbfs flat namespace lookup. Unsupported. + */ +/* ARGSUSED */ +static int smbfs_vget(mp, ino, vpp) + struct mount *mp; + ino_t ino; + struct vnode **vpp; +{ + return (EOPNOTSUPP); +} + +/* ARGSUSED */ +static int smbfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) + struct mount *mp; + struct fid *fhp; + struct sockaddr *nam; + struct vnode **vpp; + int *exflagsp; + struct ucred **credanonp; +{ + return (EINVAL); +} + +/* + * Vnode pointer to File handle, should never happen either + */ +/* ARGSUSED */ +static int +smbfs_vptofh(vp, fhp) + struct vnode *vp; + struct fid *fhp; +{ + return (EINVAL); +} + +#endif /* __FreeBSD_version < 400009 */ diff --git a/sys/netsmb/smb_trantcp.c b/sys/netsmb/smb_trantcp.c new file mode 100644 index 000000000000..3d6b0827b99c --- /dev/null +++ b/sys/netsmb/smb_trantcp.c @@ -0,0 +1,690 @@ +/* + * Copyright (c) 2000-2001 Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/poll.h> +#include <sys/uio.h> +#include <sys/sysctl.h> +#include <sys/condvar.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <sys/mchain.h> + +#include <netsmb/netbios.h> + +#include <netsmb/smb.h> +#include <netsmb/smb_conn.h> +#include <netsmb/smb_tran.h> +#include <netsmb/smb_trantcp.h> +#include <netsmb/smb_subr.h> + +#define M_NBDATA M_PCB + +static int smb_tcpsndbuf = 10 * 1024; +static int smb_tcprcvbuf = 10 * 1024; + +SYSCTL_DECL(_net_smb); +SYSCTL_INT(_net_smb, OID_AUTO, tcpsndbuf, CTLFLAG_RW, &smb_tcpsndbuf, 0, ""); +SYSCTL_INT(_net_smb, OID_AUTO, tcprcvbuf, CTLFLAG_RW, &smb_tcprcvbuf, 0, ""); + +#define nb_sosend(so,m,flags,p) (so)->so_proto->pr_usrreqs->pru_sosend( \ + so, NULL, 0, m, 0, flags, p) + +static int nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp, + u_int8_t *rpcodep, struct proc *p); +static int smb_nbst_disconnect(struct smb_vc *vcp, struct proc *p); + +static int +nb_setsockopt_int(struct socket *so, int level, int name, int val) +{ + struct sockopt sopt; + + bzero(&sopt, sizeof(sopt)); + sopt.sopt_level = level; + sopt.sopt_name = name; + sopt.sopt_val = &val; + sopt.sopt_valsize = sizeof(val); + return sosetopt(so, &sopt); +} + +static __inline int +nb_poll(struct nbpcb *nbp, int events, struct proc *p) +{ + return nbp->nbp_tso->so_proto->pr_usrreqs->pru_sopoll(nbp->nbp_tso, + events, NULL, p); +} + +static int +nbssn_rselect(struct nbpcb *nbp, struct timeval *tv, int events, struct proc *p) +{ + struct timeval atv, rtv, ttv; + int timo, error; + + if (tv) { + atv = *tv; + if (itimerfix(&atv)) { + error = EINVAL; + goto done_noproclock; + } + getmicrouptime(&rtv); + timevaladd(&atv, &rtv); + } + timo = 0; + PROC_LOCK(p); + p->p_flag |= P_SELECT; + PROC_UNLOCK(p); + error = nb_poll(nbp, events, p); + PROC_LOCK(p); + if (error) { + error = 0; + goto done; + } + if (tv) { + getmicrouptime(&rtv); + if (timevalcmp(&rtv, &atv, >=)) { + /* + * An event of our interest may occur during locking a process. + * In order to avoid missing the event that occured during locking + * the process, test P_SELECT and rescan file descriptors if + * necessary. + */ + if ((p->p_flag & P_SELECT) == 0) { + p->p_flag |= P_SELECT; + PROC_UNLOCK(p); + error = nb_poll(nbp, events, p); + PROC_LOCK(p); + } + goto done; + } + ttv = atv; + timevalsub(&ttv, &rtv); + timo = tvtohz(&ttv); + } + p->p_flag &= ~P_SELECT; + if (timo > 0) + error = cv_timedwait(&selwait, &p->p_mtx, timo); + else { + cv_wait(&selwait, &p->p_mtx); + error = 0; + } + +done: + PROC_UNLOCK(p); + p->p_flag &= ~P_SELECT; +done_noproclock: + if (error == ERESTART) + return 0; + return error; +} + +static int +nb_intr(struct nbpcb *nbp, struct proc *p) +{ + return 0; +} + +static void +nb_upcall(struct socket *so, void *arg, int waitflag) +{ + struct nbpcb *nbp = arg; + + if (arg == NULL || nbp->nbp_selectid == NULL) + return; + wakeup(nbp->nbp_selectid); +} + +static int +nb_sethdr(struct mbuf *m, u_int8_t type, u_int32_t len) +{ + u_int32_t *p = mtod(m, u_int32_t *); + + *p = htonl((len & 0x1FFFF) | (type << 24)); + return 0; +} + +static int +nb_put_name(struct mbchain *mbp, struct sockaddr_nb *snb) +{ + int error; + u_char seglen, *cp; + + cp = snb->snb_name; + if (*cp == 0) + return EINVAL; + NBDEBUG("[%s]\n", cp); + for (;;) { + seglen = (*cp) + 1; + error = mb_put_mem(mbp, cp, seglen, MB_MSYSTEM); + if (error) + return error; + if (seglen == 1) + break; + cp += seglen; + } + return 0; +} + +static int +nb_connect_in(struct nbpcb *nbp, struct sockaddr_in *to, struct proc *p) +{ + struct socket *so; + int error, s; + + error = socreate(AF_INET, &so, SOCK_STREAM, IPPROTO_TCP, p); + if (error) + return error; + nbp->nbp_tso = so; + so->so_upcallarg = (caddr_t)nbp; + so->so_upcall = nb_upcall; + so->so_rcv.sb_flags |= SB_UPCALL; + so->so_rcv.sb_timeo = (5 * hz); + so->so_snd.sb_timeo = (5 * hz); + error = soreserve(so, nbp->nbp_sndbuf, nbp->nbp_rcvbuf); + if (error) + goto bad; + nb_setsockopt_int(so, SOL_SOCKET, SO_KEEPALIVE, 1); + nb_setsockopt_int(so, IPPROTO_TCP, TCP_NODELAY, 1); + so->so_rcv.sb_flags &= ~SB_NOINTR; + so->so_snd.sb_flags &= ~SB_NOINTR; + error = soconnect(so, (struct sockaddr*)to, p); + if (error) + goto bad; + s = splnet(); + while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { + tsleep(&so->so_timeo, PSOCK, "nbcon", 2 * hz); + if ((so->so_state & SS_ISCONNECTING) && so->so_error == 0 && + (error = nb_intr(nbp, p)) != 0) { + so->so_state &= ~SS_ISCONNECTING; + splx(s); + goto bad; + } + } + if (so->so_error) { + error = so->so_error; + so->so_error = 0; + splx(s); + goto bad; + } + splx(s); + return 0; +bad: + smb_nbst_disconnect(nbp->nbp_vc, p); + return error; +} + +static int +nbssn_rq_request(struct nbpcb *nbp, struct proc *p) +{ + struct mbchain mb, *mbp = &mb; + struct mdchain md, *mdp = &md; + struct mbuf *m0; + struct timeval tv; + struct sockaddr_in sin; + u_short port; + u_int8_t rpcode; + int error, rplen; + + error = mb_init(mbp); + if (error) + return error; + mb_put_uint32le(mbp, 0); + nb_put_name(mbp, nbp->nbp_paddr); + nb_put_name(mbp, nbp->nbp_laddr); + nb_sethdr(mbp->mb_top, NB_SSN_REQUEST, mb_fixhdr(mbp) - 4); + error = nb_sosend(nbp->nbp_tso, mbp->mb_top, 0, p); + if (!error) { + nbp->nbp_state = NBST_RQSENT; + } + mb_detach(mbp); + mb_done(mbp); + if (error) + return error; + TIMESPEC_TO_TIMEVAL(&tv, &nbp->nbp_timo); + error = nbssn_rselect(nbp, &tv, POLLIN, p); + if (error == EWOULDBLOCK) { /* Timeout */ + NBDEBUG("initial request timeout\n"); + return ETIMEDOUT; + } + if (error) /* restart or interrupt */ + return error; + error = nbssn_recv(nbp, &m0, &rplen, &rpcode, p); + if (error) { + NBDEBUG("recv() error %d\n", error); + return error; + } + /* + * Process NETBIOS reply + */ + if (m0) + md_initm(mdp, m0); + error = 0; + do { + if (rpcode == NB_SSN_POSRESP) { + nbp->nbp_state = NBST_SESSION; + nbp->nbp_flags |= NBF_CONNECTED; + break; + } + if (rpcode != NB_SSN_RTGRESP) { + error = ECONNABORTED; + break; + } + if (rplen != 6) { + error = ECONNABORTED; + break; + } + md_get_mem(mdp, (caddr_t)&sin.sin_addr, 4, MB_MSYSTEM); + md_get_uint16(mdp, &port); + sin.sin_port = port; + nbp->nbp_state = NBST_RETARGET; + smb_nbst_disconnect(nbp->nbp_vc, p); + error = nb_connect_in(nbp, &sin, p); + if (!error) + error = nbssn_rq_request(nbp, p); + if (error) { + smb_nbst_disconnect(nbp->nbp_vc, p); + break; + } + } while(0); + if (m0) + md_done(mdp); + return error; +} + +static int +nbssn_recvhdr(struct nbpcb *nbp, int *lenp, + u_int8_t *rpcodep, int flags, struct proc *p) +{ + struct socket *so = nbp->nbp_tso; + struct uio auio; + struct iovec aio; + u_int32_t len; + int error; + + aio.iov_base = (caddr_t)&len; + aio.iov_len = sizeof(len); + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_READ; + auio.uio_offset = 0; + auio.uio_resid = sizeof(len); + auio.uio_procp = p; + error = so->so_proto->pr_usrreqs->pru_soreceive + (so, (struct sockaddr **)NULL, &auio, + (struct mbuf **)NULL, (struct mbuf **)NULL, &flags); + if (error) + return error; + if (auio.uio_resid > 0) { + SMBSDEBUG("short reply\n"); + return EPIPE; + } + len = ntohl(len); + *rpcodep = (len >> 24) & 0xFF; + len &= 0x1ffff; + if (len > SMB_MAXPKTLEN) { + SMBERROR("packet too long (%d)\n", len); + return EFBIG; + } + *lenp = len; + return 0; +} + +static int +nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp, + u_int8_t *rpcodep, struct proc *p) +{ + struct socket *so = nbp->nbp_tso; + struct uio auio; + struct mbuf *m; + u_int8_t rpcode; + int len; + int error, rcvflg; + + if (so == NULL) + return ENOTCONN; + + if (mpp) + *mpp = NULL; + for(;;) { + m = NULL; + error = nbssn_recvhdr(nbp, &len, &rpcode, MSG_DONTWAIT, p); + if (so->so_state & + (SS_ISDISCONNECTING | SS_ISDISCONNECTED | SS_CANTRCVMORE)) { + nbp->nbp_state = NBST_CLOSED; + NBDEBUG("session closed by peer\n"); + return ECONNRESET; + } + if (error) + return error; + if (len == 0 && nbp->nbp_state != NBST_SESSION) + break; + if (rpcode == NB_SSN_KEEPALIVE) + continue; + bzero(&auio, sizeof(auio)); + auio.uio_resid = len; + auio.uio_procp = p; + do { + rcvflg = MSG_WAITALL; + error = so->so_proto->pr_usrreqs->pru_soreceive + (so, (struct sockaddr **)NULL, + &auio, &m, (struct mbuf **)NULL, &rcvflg); + } while (error == EWOULDBLOCK || error == EINTR || + error == ERESTART); + if (error) + break; + if (auio.uio_resid > 0) { + SMBERROR("packet is shorter than expected\n"); + error = EPIPE; + break; + } + if (nbp->nbp_state == NBST_SESSION && + rpcode == NB_SSN_MESSAGE) + break; + NBDEBUG("non-session packet %x\n", rpcode); + if (m) + m_freem(m); + } + if (error) { + if (m) + m_freem(m); + return error; + } + if (mpp) + *mpp = m; + else + m_freem(m); + *lenp = len; + *rpcodep = rpcode; + return 0; +} + +/* + * SMB transport interface + */ +static int +smb_nbst_create(struct smb_vc *vcp, struct proc *p) +{ + struct nbpcb *nbp; + + MALLOC(nbp, struct nbpcb *, sizeof *nbp, M_NBDATA, M_WAITOK); + bzero(nbp, sizeof *nbp); + nbp->nbp_timo.tv_sec = 15; /* XXX: sysctl ? */ + nbp->nbp_state = NBST_CLOSED; + nbp->nbp_vc = vcp; + nbp->nbp_sndbuf = smb_tcpsndbuf; + nbp->nbp_rcvbuf = smb_tcprcvbuf; + vcp->vc_tdata = nbp; + return 0; +} + +static int +smb_nbst_done(struct smb_vc *vcp, struct proc *p) +{ + struct nbpcb *nbp = vcp->vc_tdata; + + if (nbp == NULL) + return ENOTCONN; + smb_nbst_disconnect(vcp, p); + if (nbp->nbp_laddr) + free(nbp->nbp_laddr, M_SONAME); + if (nbp->nbp_paddr) + free(nbp->nbp_paddr, M_SONAME); + free(nbp, M_NBDATA); + return 0; +} + +static int +smb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap, struct proc *p) +{ + struct nbpcb *nbp = vcp->vc_tdata; + struct sockaddr_nb *snb; + int error, slen; + + NBDEBUG("\n"); + error = EINVAL; + do { + if (nbp->nbp_flags & NBF_LOCADDR) + break; + /* + * It is possible to create NETBIOS name in the kernel, + * but nothing prevents us to do it in the user space. + */ + if (sap == NULL) + break; + slen = sap->sa_len; + if (slen < NB_MINSALEN) + break; + snb = (struct sockaddr_nb*)dup_sockaddr(sap, 1); + if (snb == NULL) { + error = ENOMEM; + break; + } + nbp->nbp_laddr = snb; + nbp->nbp_flags |= NBF_LOCADDR; + error = 0; + } while(0); + return error; +} + +static int +smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap, struct proc *p) +{ + struct nbpcb *nbp = vcp->vc_tdata; + struct sockaddr_in sin; + struct sockaddr_nb *snb; + struct timespec ts1, ts2; + int error, slen; + + NBDEBUG("\n"); + if (nbp->nbp_tso != NULL) + return EISCONN; + if (nbp->nbp_laddr == NULL) + return EINVAL; + slen = sap->sa_len; + if (slen < NB_MINSALEN) + return EINVAL; + if (nbp->nbp_paddr) { + free(nbp->nbp_paddr, M_SONAME); + nbp->nbp_paddr = NULL; + } + snb = (struct sockaddr_nb*)dup_sockaddr(sap, 1); + if (snb == NULL) + return ENOMEM; + nbp->nbp_paddr = snb; + sin = snb->snb_addrin; + getnanotime(&ts1); + error = nb_connect_in(nbp, &sin, p); + if (error) + return error; + getnanotime(&ts2); + timespecsub(&ts2, &ts1); + if (ts2.tv_sec == 0 && ts2.tv_sec == 0) + ts2.tv_sec = 1; + nbp->nbp_timo = ts2; + timespecadd(&nbp->nbp_timo, &ts2); + timespecadd(&nbp->nbp_timo, &ts2); + timespecadd(&nbp->nbp_timo, &ts2); /* * 4 */ + error = nbssn_rq_request(nbp, p); + if (error) + smb_nbst_disconnect(vcp, p); + return error; +} + +static int +smb_nbst_disconnect(struct smb_vc *vcp, struct proc *p) +{ + struct nbpcb *nbp = vcp->vc_tdata; + struct socket *so; + + if (nbp == NULL || nbp->nbp_tso == NULL) + return ENOTCONN; + if ((so = nbp->nbp_tso) != NULL) { + nbp->nbp_flags &= ~NBF_CONNECTED; + nbp->nbp_tso = (struct socket *)NULL; + soshutdown(so, 2); + soclose(so); + } + if (nbp->nbp_state != NBST_RETARGET) { + nbp->nbp_state = NBST_CLOSED; + } + return 0; +} + +static int +smb_nbst_send(struct smb_vc *vcp, struct mbuf *m0, struct proc *p) +{ + struct nbpcb *nbp = vcp->vc_tdata; + int error; + + if (nbp->nbp_state != NBST_SESSION) { + error = ENOTCONN; + goto abort; + } + M_PREPEND(m0, 4, M_WAITOK); + if (m0 == NULL) + return ENOBUFS; + nb_sethdr(m0, NB_SSN_MESSAGE, m_fixhdr(m0) - 4); + error = nb_sosend(nbp->nbp_tso, m0, 0, p); + return error; +abort: + if (m0) + m_freem(m0); + return error; +} + + +static int +smb_nbst_recv(struct smb_vc *vcp, struct mbuf **mpp, struct proc *p) +{ + struct nbpcb *nbp = vcp->vc_tdata; + u_int8_t rpcode; + int error, rplen; + + nbp->nbp_flags |= NBF_RECVLOCK; + error = nbssn_recv(nbp, mpp, &rplen, &rpcode, p); + nbp->nbp_flags &= ~NBF_RECVLOCK; + return error; +} + +static void +smb_nbst_timo(struct smb_vc *vcp) +{ + return; +} + +static void +smb_nbst_intr(struct smb_vc *vcp) +{ + struct nbpcb *nbp = vcp->vc_tdata; + + if (nbp == NULL || nbp->nbp_tso == NULL) + return; + sorwakeup(nbp->nbp_tso); + sowwakeup(nbp->nbp_tso); +} + +static int +smb_nbst_getparam(struct smb_vc *vcp, int param, void *data) +{ + struct nbpcb *nbp = vcp->vc_tdata; + + switch (param) { + case SMBTP_SNDSZ: + *(int*)data = nbp->nbp_sndbuf; + break; + case SMBTP_RCVSZ: + *(int*)data = nbp->nbp_rcvbuf; + break; + case SMBTP_TIMEOUT: + *(struct timespec*)data = nbp->nbp_timo; + break; + default: + return EINVAL; + } + return 0; +} + +static int +smb_nbst_setparam(struct smb_vc *vcp, int param, void *data) +{ + struct nbpcb *nbp = vcp->vc_tdata; + + switch (param) { + case SMBTP_SELECTID: + nbp->nbp_selectid = data; + break; + default: + return EINVAL; + } + return 0; +} + +/* + * Check for fatal errors + */ +static int +smb_nbst_fatal(struct smb_vc *vcp, int error) +{ + switch (error) { + case ENOTCONN: + case ENETRESET: + case ECONNABORTED: + return 1; + } + return 0; +} + + +struct smb_tran_desc smb_tran_nbtcp_desc = { + SMBT_NBTCP, + smb_nbst_create, smb_nbst_done, + smb_nbst_bind, smb_nbst_connect, smb_nbst_disconnect, + smb_nbst_send, smb_nbst_recv, + smb_nbst_timo, smb_nbst_intr, + smb_nbst_getparam, smb_nbst_setparam, + smb_nbst_fatal +}; + diff --git a/sys/pccard/mecia.c b/sys/pccard/mecia.c new file mode 100644 index 000000000000..76669c8ea9d3 --- /dev/null +++ b/sys/pccard/mecia.c @@ -0,0 +1,730 @@ +/* + * NEC MECIA controller. + *------------------------------------------------------------------------- + * + * Copyright (c) 2001 M. Warner Losh. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + * Based heavily on the FreeBSD pcic driver's pcic98 support, derived + * from PAO3 tree. This copyright notice likely needs modification for + * such a linage. The only authorship I could find was: + * + * PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L. + * by Noriyuki Hosobuchi <hoso@ce.mbn.or.jp> + */ + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <pccard/meciareg.h> +#include <pccard/cardinfo.h> +#include <pccard/slot.h> +#ifndef MECIA_IOBASE +#define MECIA_IOBASE 0x80d0 +#endif + +/* Get pnp IDs */ +#include <isa/isavar.h> + +#include <dev/pccard/pccardvar.h> +#include "card_if.h" + +#define MECIA_DEVICE2SOFTC(dev) ((struct mecia_slot *) device_get_softc(dev)) + +/* + * Prototypes for interrupt handler. + */ +static driver_intr_t meciaintr; +static int mecia_ioctl(struct slot *, int, caddr_t); +static int mecia_power(struct slot *); +static void mecia_mapirq(struct slot *, int); +static timeout_t mecia_reset; +static void mecia_resume(struct slot *); +static void mecia_disable(struct slot *); +static timeout_t meciatimeout; +static struct callout_handle meciatimeout_ch + = CALLOUT_HANDLE_INITIALIZER(&meciatimeout_ch); +static int mecia_memory(struct slot *, int); +static int mecia_io(struct slot *, int); + +/* + * Per-slot data table. + */ +struct mecia_slot { + int unit; /* Unit number */ + int slotnum; /* My slot number */ + struct slot *slt; /* Back ptr to slot */ + device_t dev; /* My device */ + u_char last_reg1; /* Last value of change reg */ +}; + +static struct slot_ctrl mecia_cinfo = { + mecia_mapirq, + mecia_memory, + mecia_io, + mecia_reset, + mecia_disable, + mecia_power, + mecia_ioctl, + mecia_resume, + 1, +#if 0 + 1 +#else + 2 /* Fake for UE2212 LAN card */ +#endif +}; + +static int validunits = 0; + +/* + * Look for an NEC MECIA. + * For each available slot, allocate a PC-CARD slot. + */ + +static int +mecia_probe(device_t dev) +{ + int validslots = 0; + + /* Check isapnp ids */ + if (isa_get_logicalid(dev)) /* skip PnP probes */ + return (ENXIO); + + if (inb(MECIA_REG0) != 0xff) { + validslots++; + /* XXX need to allocated the port resources */ + device_set_desc(dev, "MECIA PC98 Original PCMCIA Controller"); + } + return (validslots ? 0 : ENXIO); +} + +static int +mecia_attach(device_t dev) +{ + int error; + int irq; + void *ih; + device_t kid; + struct resource *r; + int rid; + struct slot *slt; + struct mecia_slot *sp; + + sp = MECIA_DEVICE2SOFTC(dev); + sp->unit = validunits++; + kid = device_add_child(dev, NULL, -1); + if (kid == NULL) { + device_printf(dev, "Can't add pccard bus slot 0\n"); + return (ENXIO); + } + device_probe_and_attach(kid); + slt = pccard_init_slot(kid, &mecia_cinfo); + if (slt == 0) { + device_printf(dev, "Can't get pccard info slot 0\n"); + return (ENXIO); + } + slt->cdata = sp; + sp->slt = slt; + validunits++; + + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + if (!r) + return (ENXIO); + + irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); + if (irq == 0) { + /* See if the user has requested a specific IRQ */ + if (!getenv_int("machdep.pccard.mecia_irq", &irq)) + irq = 0; + } + rid = 0; + r = 0; + if (irq > 0) { + r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, + irq, 1, RF_ACTIVE); + } + if (r && ((1 << (rman_get_start(r))) & MECIA_INT_MASK_ALLOWED) == 0) { + device_printf(dev, + "Hardware does not support irq %d, trying polling.\n", + irq); + bus_release_resource(dev, SYS_RES_IRQ, rid, r); + r = 0; + irq = 0; + } + if (r) { + error = bus_setup_intr(dev, r, INTR_TYPE_MISC, + meciaintr, (void *) sp, &ih); + if (error) { + bus_release_resource(dev, SYS_RES_IRQ, rid, r); + return (error); + } + irq = rman_get_start(r); + device_printf(dev, "management irq %d\n", irq); + } else { + irq = 0; + } + if (irq == 0) { + meciatimeout_ch = timeout(meciatimeout, (void *) sp, hz/2); + device_printf(dev, "Polling mode\n"); + } + + sp->last_reg1 = inb(MECIA_REG1); + if (sp->last_reg1 & MECIA_CARDEXIST) { + /* PCMCIA card exist */ + sp->slt->laststate = sp->slt->state = filled; + pccard_event(sp->slt, card_inserted); + } else { + sp->slt->laststate = sp->slt->state = empty; + } + sp->slt->irq = irq; + + return (bus_generic_attach(dev)); +} + +/* + * ioctl calls - Controller specific ioctls + */ +static int +mecia_ioctl(struct slot *slt, int cmd, caddr_t data) +{ + return (ENOTTY); +} + +/* + * MECIA timer. If the controller doesn't have a free IRQ to use + * or if interrupt steering doesn't work, poll the controller for + * insertion/removal events. + */ +static void +meciatimeout(void *chan) +{ + meciaintr(chan); + meciatimeout_ch = timeout(meciatimeout, chan, hz/2); +} + +/* + * MECIA Interrupt handler. + * Check the slot and report any changes. + */ +static void +meciaintr(void *arg) +{ + u_char reg1; + int s; + struct mecia_slot *sp = (struct mecia_slot *) arg; + + s = splhigh(); + /* Check for a card in this slot */ + reg1 = inb(MECIA_REG1); + if ((sp->last_reg1 ^ reg1) & MECIA_CARDEXIST) { + sp->last_reg1 = reg1; + if (reg1 & MECIA_CARDEXIST) + pccard_event(sp->slt, card_inserted); + else + pccard_event(sp->slt, card_removed); + } + splx(s); +} + +/* + * local functions for PC-98 Original PC-Card controller + */ +#define MECIA_ALWAYS_128MAPPING 1 /* trick for using UE2212 */ + +int mecia_mode = 0; /* almost the same as the value in MECIA_REG2 */ + +static unsigned char reg_winsel = MECIA_UNMAPWIN; +static unsigned short reg_pagofs = 0; + +static int +mecia_memory(struct slot *slt, int win) +{ + struct mem_desc *mp = &slt->mem[win]; + unsigned char x; + + if (mp->flags & MDF_ACTIVE) { + /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */ + if ((unsigned long)mp->start != 0xda000) { + printf( + "sys_addr must be 0xda000. requested address = %p\n", + mp->start); + return (EINVAL); + } + + /* omajinai ??? */ + outb(MECIA_REG0, 0); + x = inb(MECIA_REG1); + x &= 0xfc; + x |= 0x02; + outb(MECIA_REG1, x); + reg_winsel = inb(MECIA_REG_WINSEL); + reg_pagofs = inw(MECIA_REG_PAGOFS); + outb(MECIA_REG_WINSEL, MECIA_MAPWIN); + outw(MECIA_REG_PAGOFS, (mp->card >> 13)); /* 8KB */ + + if (mp->flags & MDF_ATTR) + outb(MECIA_REG7, inb(MECIA_REG7) | MECIA_ATTRMEM); + else + outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_ATTRMEM)); + + outb(MECIA_REG_WINSEL, MECIA_MAPWIN); +#if 0 + if ((mp->flags & MDF_16BITS) == 1) /* 16bit */ + outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_8BIT)); + else /* 8bit */ + outb(MECIA_REG2, inb(MECIA_REG2) | MECIA_8BIT); +#endif + } else { /* !(mp->flags & MDF_ACTIVE) */ + outb(MECIA_REG0, 0); + x = inb(MECIA_REG1); + x &= 0xfc; + x |= 0x02; + outb(MECIA_REG1, x); +#if 0 + outb(MECIA_REG_WINSEL, MECIA_UNMAPWIN); + outw(MECIA_REG_PAGOFS, 0); +#else + outb(MECIA_REG_WINSEL, reg_winsel); + outw(MECIA_REG_PAGOFS, reg_pagofs); +#endif + } + return (0); +} + +static int +mecia_io(struct slot *slt, int win) +{ + struct io_desc *ip = &slt->io[win]; + unsigned char x; + unsigned short cardbase; + u_short ofst; + + if (win != 0) { + /* ignore for UE2212 */ + printf( + "mecia:Illegal MECIA I/O window(%d) request! Ignored.\n", win); +/* return (EINVAL);*/ + return (0); + } + + if (ip->flags & IODF_ACTIVE) { + x = inb(MECIA_REG2) & 0x0f; +#if 0 + if (! (ip->flags & IODF_CS16)) + x |= MECIA_8BIT; +#else + if (! (ip->flags & IODF_16BIT)) { + x |= MECIA_8BIT; + mecia_mode |= MECIA_8BIT; + } +#endif + + ofst = ip->start & 0xf; + cardbase = ip->start & ~0xf; +#ifndef MECIA_ALWAYS_128MAPPING + if (ip->size + ofst > 16) +#endif + { /* 128bytes mapping */ + x |= MECIA_MAP128; + mecia_mode |= MECIA_MAP128; + ofst |= ((cardbase & 0x70) << 4); + cardbase &= ~0x70; + } + + x |= MECIA_MAPIO; + outb(MECIA_REG2, x); + + outw(MECIA_REG4, MECIA_IOBASE); /* 98side I/O base */ + outw(MECIA_REG5, cardbase); /* card side I/O base */ + + if (bootverbose) { + printf("mecia: I/O mapped 0x%04x(98) -> " + "0x%04x(Card) and width %d bytes\n", + MECIA_IOBASE+ofst, ip->start, ip->size); + printf("mecia: reg2=0x%02x reg3=0x%02x reg7=0x%02x\n", + inb(MECIA_REG2), inb(MECIA_REG3), + inb(MECIA_REG7)); + printf("mecia: mode=%d\n", mecia_mode); + } + + ip->start = MECIA_IOBASE + ofst; + } else { + outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO)); + mecia_mode = 0; + } + return (0); +} + +static int +mecia_power(struct slot *slt) +{ + unsigned char reg; + + reg = inb(MECIA_REG7) & (~MECIA_VPP12V); + switch(slt->pwr.vpp) { + default: + return (EINVAL); + case 50: + break; + case 120: + reg |= MECIA_VPP12V; + break; + } + outb(MECIA_REG7, reg); + DELAY(100*1000); + + reg = inb(MECIA_REG2) & (~MECIA_VCC3P3V); + switch(slt->pwr.vcc) { + default: + return (EINVAL); + case 33: + reg |= MECIA_VCC3P3V; + break; + case 50: + break; + } + outb(MECIA_REG2, reg); + DELAY(100*1000); + return (0); +} + +static void +mecia_mapirq(struct slot *slt, int irq) +{ + u_char x; + + switch (irq) { + case 3: + x = MECIA_INT0; + break; + case 5: + x = MECIA_INT1; + break; + case 6: + x = MECIA_INT2; + break; + case 10: + x = MECIA_INT4; + break; + case 12: + x = MECIA_INT5; + break; + case 0: /* disable */ + x = MECIA_INTDISABLE; + break; + default: + printf("mecia: illegal irq %d\n", irq); + return; + } +#ifdef MECIA_DEBUG + printf("mecia: irq=%d mapped.\n", irq); +#endif + outb(MECIA_REG3, x); +} + +static void +mecia_reset(void *chan) +{ + struct slot *slt = chan; + + outb(MECIA_REG0, 0); + outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO)); + outb(MECIA_REG3, MECIA_INTDISABLE); +#if 0 +/* mecia_reset() is called after mecia_power() */ + outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_VCC3P3V)); + outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_VPP12V)); +#endif + outb(MECIA_REG1, 0); + + selwakeup(&slt->selp); +} + +static void +mecia_disable(struct slot *slt) +{ + /* null function */ +} + +static void +mecia_resume(struct slot *slt) +{ + /* XXX MECIA How ? */ +} + +static int +mecia_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + int err; + + if (dev != device_get_parent(device_get_parent(child)) || devi == NULL) + return (bus_generic_activate_resource(dev, child, type, + rid, r)); + + switch (type) { + case SYS_RES_IOPORT: { + struct io_desc *ip; + ip = &devi->slt->io[rid]; + if (ip->flags == 0) { + if (rid == 0) + ip->flags = IODF_WS | IODF_16BIT | IODF_CS16; + else + ip->flags = devi->slt->io[0].flags; + } + ip->flags |= IODF_ACTIVE; + ip->start = rman_get_start(r); + ip->size = rman_get_end(r) - rman_get_start(r) + 1; + err = mecia_cinfo.mapio(devi->slt, rid); + if (err) + return (err); + break; + } + case SYS_RES_IRQ: + /* + * We actually defer the activation of the IRQ resource + * until the interrupt is registered to avoid stray + * interrupt messages. + */ + break; + case SYS_RES_MEMORY: { + struct mem_desc *mp; + if (rid >= NUM_MEM_WINDOWS) + return (EINVAL); + mp = &devi->slt->mem[rid]; + mp->flags |= MDF_ACTIVE; + mp->start = (caddr_t) rman_get_start(r); + mp->size = rman_get_end(r) - rman_get_start(r) + 1; + err = mecia_cinfo.mapmem(devi->slt, rid); + if (err) + return (err); + break; + } + default: + break; + } + err = bus_generic_activate_resource(dev, child, type, rid, r); + return (err); +} + +static int +mecia_deactivate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + int err; + + if (dev != device_get_parent(device_get_parent(child)) || devi == NULL) + return (bus_generic_deactivate_resource(dev, child, type, + rid, r)); + + switch (type) { + case SYS_RES_IOPORT: { + struct io_desc *ip = &devi->slt->io[rid]; + ip->flags &= ~IODF_ACTIVE; + err = mecia_cinfo.mapio(devi->slt, rid); + if (err) + return (err); + break; + } + case SYS_RES_IRQ: + break; + case SYS_RES_MEMORY: { + struct mem_desc *mp = &devi->slt->mem[rid]; + mp->flags &= ~(MDF_ACTIVE | MDF_ATTR); + err = mecia_cinfo.mapmem(devi->slt, rid); + if (err) + return (err); + break; + } + default: + break; + } + err = bus_generic_deactivate_resource(dev, child, type, rid, r); + return (err); +} + +static int +mecia_setup_intr(device_t dev, device_t child, struct resource *irq, + int flags, driver_intr_t *intr, void *arg, void **cookiep) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + int err; + + if (((1 << rman_get_start(irq)) & MECIA_INT_MASK_ALLOWED) == 0) { + device_printf(dev, "Hardware does not support irq %ld.\n", + rman_get_start(irq)); + return (EINVAL); + } + + err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, + cookiep); + if (err == 0) + mecia_cinfo.mapirq(devi->slt, rman_get_start(irq)); + else + device_printf(dev, "Error %d irq %ld\n", err, + rman_get_start(irq)); + return (err); +} + +static int +mecia_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + + mecia_cinfo.mapirq(devi->slt, 0); + return (bus_generic_teardown_intr(dev, child, irq, cookie)); +} + +static int +mecia_set_res_flags(device_t bus, device_t child, int restype, int rid, + u_long value) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + int err = 0; + + switch (restype) { + case SYS_RES_MEMORY: { + struct mem_desc *mp = &devi->slt->mem[rid]; + switch (value) { + case PCCARD_A_MEM_COM: + mp->flags &= ~MDF_ATTR; + break; + case PCCARD_A_MEM_ATTR: + mp->flags |= MDF_ATTR; + break; + case PCCARD_A_MEM_8BIT: + mp->flags &= ~MDF_16BITS; + break; + case PCCARD_A_MEM_16BIT: + mp->flags |= MDF_16BITS; + break; + } + err = mecia_cinfo.mapmem(devi->slt, rid); + break; + } + default: + err = EOPNOTSUPP; + } + return (err); +} + +static int +mecia_get_res_flags(device_t bus, device_t child, int restype, int rid, + u_long *value) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + int err = 0; + + if (value == 0) + return (ENOMEM); + + switch (restype) { + case SYS_RES_IOPORT: { + struct io_desc *ip = &devi->slt->io[rid]; + *value = ip->flags; + break; + } + case SYS_RES_MEMORY: { + struct mem_desc *mp = &devi->slt->mem[rid]; + *value = mp->flags; + break; + } + default: + err = EOPNOTSUPP; + } + return (err); +} + +static int +mecia_set_memory_offset(device_t bus, device_t child, int rid, + u_int32_t offset, u_int32_t *deltap) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + struct mem_desc *mp = &devi->slt->mem[rid]; + + mp->card = offset; + if (deltap) + *deltap = 0; /* XXX BAD XXX */ + return (mecia_cinfo.mapmem(devi->slt, rid)); +} + +static int +mecia_get_memory_offset(device_t bus, device_t child, int rid, + u_int32_t *offset) +{ + struct pccard_devinfo *devi = device_get_ivars(child); + struct mem_desc *mp = &devi->slt->mem[rid]; + + if (offset == 0) + return (ENOMEM); + + *offset = mp->card; + + return (0); +} + +static device_method_t mecia_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, mecia_probe), + DEVMETHOD(device_attach, mecia_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, mecia_activate_resource), + DEVMETHOD(bus_deactivate_resource, mecia_deactivate_resource), + DEVMETHOD(bus_setup_intr, mecia_setup_intr), + DEVMETHOD(bus_teardown_intr, mecia_teardown_intr), + + /* Card interface */ + DEVMETHOD(card_set_res_flags, mecia_set_res_flags), + DEVMETHOD(card_get_res_flags, mecia_get_res_flags), + DEVMETHOD(card_set_memory_offset, mecia_set_memory_offset), + DEVMETHOD(card_get_memory_offset, mecia_get_memory_offset), + + { 0, 0 } +}; + +devclass_t mecia_devclass; + +static driver_t mecia_driver = { + "mecia", + mecia_methods, + sizeof(struct mecia_slot) +}; + +DRIVER_MODULE(mecia, isa, mecia_driver, mecia_devclass, 0, 0); diff --git a/sys/pccard/meciareg.h b/sys/pccard/meciareg.h new file mode 100644 index 000000000000..b54ae4d61843 --- /dev/null +++ b/sys/pccard/meciareg.h @@ -0,0 +1,60 @@ +/* + * meciareg.h + * + * PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L. + * by Noriyuki Hosobuchi <hoso@ce.mbn.or.jp> + * + * $FreeBSD$ + */ + +/*--- I/O port definition */ +#define MECIA_REG0 0x0a8e /* byte */ +#define MECIA_REG1 0x1a8e /* byte */ +#define MECIA_REG2 0x2a8e /* byte */ +#define MECIA_REG3 0x3a8e /* byte : Interrupt */ +#define MECIA_REG4 0x4a8e /* word : PC98 side I/O base */ +#define MECIA_REG5 0x5a8e /* word : Card side I/O base */ +#define MECIA_REG7 0x7a8e /* byte */ + +#define MECIA_REG_WINSEL 0x1e8e /* byte : win bank select register */ +#define MECIA_REG_PAGOFS 0x0e8e /* word */ + +/* PC98_REG_WINSEL */ +#define MECIA_MAPWIN 0x84 /* map Card on 0xda0000 - 0xdbffff */ +#define MECIA_UNMAPWIN 0x00 + +/* MECIA_REG1 */ +#define MECIA_CARDEXIST 0x08 /* 1:exist 0:not exist */ + +/* MECIA_REG2 */ +#define MECIA_MAPIO 0x80 /* 1:I/O 0:Memory */ +#define MECIA_IOTHROUGH 0x40 /* 0:I/O map 1:I/O addr-through */ +#define MECIA_8BIT 0x20 /* bit width 1:8bit 0:16bit */ +#define MECIA_MAP128 0x10 /* I/O map size 1:128byte 0:16byte */ +#define MECIA_VCC3P3V 0x02 /* Vcc 1:3.3V 0:5.0V */ + +/* MECIA_REG3 */ +#define MECIA_INT0 (0xf8 + 0x0) /* INT0(IRQ3) */ +#define MECIA_INT1 (0xf8 + 0x1) /* INT1(IRQ5) */ +#define MECIA_INT2 (0xf8 + 0x2) /* INT2(IRQ6) */ +#define MECIA_INT4 (0xf8 + 0x4) /* INT4(IRQ10) */ +#define MECIA_INT5 (0xf8 + 0x5) /* INT5(IRQ12) */ +#define MECIA_INTDISABLE (0xf8 + 0x7) /* disable interrupt */ + +/* MECIA_REG7 */ +#define MECIA_ATTRMEM 0x20 /* 1:attr mem 0:common mem */ +#define MECIA_VPP12V 0x10 /* Vpp 0:5V 1:12V */ + + +#ifdef KERNEL +extern int mecia_mode; /* in 'pccard/pcic.c' */ +#define mecia_8bit_on() \ + if (mecia_mode & MECIA_8BIT) \ + outb(MECIA_REG2, inb(MECIA_REG2) | MECIA_8BIT) +#define mecia_8bit_off() \ + if (mecia_mode & MECIA_8BIT) \ + outb(MECIA_REG2, inb(MECIA_REG2) & ~MECIA_8BIT) +#define mecia_map128() (mecia_mode & MECIA_MAP128) +#endif + +#define MECIA_INT_MASK_ALLOWED 0x3E68 /* PC98 */ |
