Mercurial > hg > waaad
view waaad/peer-secini.c @ 337:c53934b11609
Allow compilation of waaad without SCTP support (DISABLE_SCTP). Based on a patch by Chris Brody.
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Wed, 01 Apr 2009 11:15:06 +0900 |
parents | b9b74d6ac29e |
children | e86dba02630a |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@nict.go.jp> * * * * Copyright (c) 2008, WIDE Project and NICT * * All rights reserved. * * * * Redistribution and use of this software in source and binary forms, with or without modification, are * * permitted provided that the following conditions are met: * * * * * Redistributions of source code must retain the above * * copyright notice, this list of conditions and the * * following disclaimer. * * * * * 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. * * * * * Neither the name of the WIDE Project or NICT nor the * * names of its contributors may be used to endorse or * * promote products derived from this software without * * specific prior written permission of WIDE Project and * * NICT. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. * *********************************************************************************************************/ /* Peers facility. * * This file contains the code of a dummy security module to exchange data with a remote peer before identity is known. * */ #include "waaad-internal.h" #include "peer-internal.h" /* State change callback */ static int _peer_secini_state_change (sec_pss_t newstate, sec_pss_t oldstate, sec_session_t * session, void ** ext_session) { TRACE_ENTRY("%d %d %p %p", newstate, oldstate, session, ext_session); /* We don't need to save a session state in this module, so do not do anything here */ return 0; } /* Sending data: we just write the buffer unmodified on the connection object */ static int _peer_secini_send (sec_session_t * session, void ** ext_session, void * data, size_t length) { ssize_t ret = 0; size_t sent = 0; int stream = -1; TRACE_ENTRY("%p %p %p %d", session, ext_session, data, length); if (!session || !session->conn) { TRACE_DEBUG(INFO, "Invalid argument"); return EINVAL; } while (sent < length) { switch (session->proto) { case IPPROTO_TCP: ret = (*session->cbs.tcp.send_data) (session, ((char *)data) + sent, length - sent); break; #ifndef DISABLE_SCTP case IPPROTO_SCTP: ret = (*session->cbs.sctp.send_data) (session, &stream, ((char *)data) + sent, length - sent); break; #endif /* DISABLE_SCTP */ default: TRACE_DEBUG(INFO, "Invalid proto"); return EINVAL; } if (ret == -1) { ret = errno; TRACE_DEBUG(INFO, "The send_data callback failed: %s", strerror(ret)); return ret; } sent += ret; } return 0; } /* Receive from a TCP connection: rebuild the message boundaries */ static int _peer_secini_recv_tcp (sec_session_t * session, void ** data, size_t *length) { unsigned char header[4]; unsigned char * newmsg; ssize_t ret = 0; size_t received = 0; /* First, receive only a message header. */ while (received < sizeof(header)) { ret = (*session->cbs.tcp.recv_data) (session, &header[received], sizeof(header) - received); if (ret == 0) { /* Shutdown in progress */ TRACE_DEBUG(INFO, "The recv_data function returned 0"); return ENOTCONN; } CHECK_SYS(ret); /* in case of <0 value */ received += ret; } *length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; /* Check the received word is a valid begining of a Diameter message */ if ((header[0] != MSG_VERSION) /* MSG_VERSION defined in <waaad/message-api.h> */ || (*length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ /* The message is suspect */ TRACE_DEBUG(INFO, "Received suspect message header: ver = %d, size = %d", (int)header[0], *length); return EBADMSG; } /* Ok, now we can really receive the data */ CHECK_MALLOC( newmsg = malloc( *length ) ); memcpy(newmsg, header, sizeof(header)); while (received < *length) { pthread_cleanup_push(cleanup_buffer, newmsg); /* In case we are canceled, clean the partialy built buffer */ ret = (*session->cbs.tcp.recv_data) (session, newmsg + received, (*length) - received); pthread_cleanup_pop(0); if (ret == 0) { /* Shutdown in progress */ TRACE_DEBUG(INFO, "The recv_data function returned 0"); free(newmsg); return ENOTCONN; } if (ret < 0) { /* Error */ ret = errno; CHECK_SYS_DO( -1, ); free(newmsg); return ret; } received += ret; } /* We have received a full message, return it */ *data = (void *) newmsg; return 0; } #ifndef DISABLE_SCTP /* Receive from a SCTP connection: the message boundaries are preserved, so we have very few to do here */ static int _peer_secini_recv_sctp (sec_session_t * session, void ** data, size_t *length) { ssize_t ret = 0; uint16_t stream = 0; ret = (*session->cbs.sctp.recv_data) (session, &stream, data, length); if (ret == 0) { /* Shutdown in progress */ TRACE_DEBUG(INFO, "The recv_data function returned 0"); return ENOTCONN; } CHECK_SYS(ret); TRACE_DEBUG(FULL, "Received a message of %d bytes on stream %d", *length, stream); return 0; } #endif /* DISABLE_SCTP */ /* We just receive the buffer on the connection object, and rebuild a message (boundaries are lost with TCP) */ int _peer_secini_recv (sec_session_t * session, void ** ext_session, void ** data, size_t *length) { TRACE_ENTRY("%p %p %p %p", session, ext_session, data, length); CHECK_PARAMS(session && session->conn && data && length); switch (session->proto) { case IPPROTO_TCP: CHECK_FCT( _peer_secini_recv_tcp(session, data, length) ); break; #ifndef DISABLE_SCTP case IPPROTO_SCTP: CHECK_FCT( _peer_secini_recv_sctp(session, data, length) ); break; #endif /* DISABLE_SCTP */ default: TRACE_DEBUG(INFO, "Invalid proto"); return EINVAL; } return 0; } sec_module_t _peer_secini_mod = { .sec_insecid = 0, .sec_is_supported_peer = NULL, .sec_state_change = _peer_secini_state_change, .sec_send_protect = _peer_secini_send, .sec_recv_unprotect = _peer_secini_recv };