source: TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd_private.c @ 973

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd_private.c@973
Revision 973, 14.8 KB checked in by spascoe, 13 years ago (diff)

Added the private authentication API extensions needed to implement
NDG security. This API is connected to empty stub functions, no useful
functionality yet. Authorisation will require a further extension later.

The code compiles. Execution yet to be tested.

Line 
1/*
2 * bbftpd/bbftpd_private.c
3 * Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
4 * bbftp@in2p3.fr
5 * http://doc.in2p3.fr/bbftp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */ 
21
22/****************************************************************************
23
24 
25 
26 bbftpd_private.c   v 2.1.0 2001/05/21  - Routines creation
27
28*****************************************************************************/
29#include <errno.h>
30#include <netinet/in.h>
31#include <stdio.h>
32#include <syslog.h>
33#include <sys/socket.h>
34#if TIME_WITH_SYS_TIME
35# include <sys/time.h>
36# include <time.h>
37#else
38# if HAVE_SYS_TIME_H
39#  include <sys/time.h>
40# else
41#  include <time.h>
42# endif
43#endif
44#include <utime.h>
45
46#include <openssl/rsa.h>
47
48#include <bbftpd.h>
49#include <bbftpd_private.h>
50#include <config.h>
51#include <common.h>
52#include <daemon_proto.h>
53#include <daemon.h>
54#include <structures.h>
55#include <version.h>
56
57extern  int     incontrolsock ;
58extern  int     outcontrolsock ;
59extern  int         recvcontrolto ;
60extern  int         sendcontrolto ;
61extern  RSA     *myrsa ;
62
63
64/*******************************************************************************
65** bbftpd_private_receive_connection :                                         *
66**                                                                             *
67**      This routine is called when a connection occurs in private             *
68**      authentication mode. It receives the plublic key of the client and     *
69**      gives the hand to the bbftpd_private_auth routine and then if this     *
70**      routine returns 0 to set up correctly the global parameters            *
71**                                                                             *
72**      OUPUT variable :                                                       *
73**          logmessage :  to write the error message in case of error          *
74**                                                                             *
75**      GLOBAL VARIABLE USED :                                                 *                                                                      *
76**          hisrsa              MODIFIED                                       *
77**                                                                             *
78**                                                                             *
79**      RETURN:                                                                *
80**          -1  Unrecoverable error                                            *
81**           0  OK                                                             *
82**                                                                             *
83*******************************************************************************/
84int bbftpd_private_receive_connection(int msglen) 
85{
86
87    char    *receive_buffer ;
88    char    logmessage[1024] ;
89    int     lenkey ;
90    int     lenexpo ;
91    unsigned char   *pubkey ;
92    unsigned char   *pubexponent ;
93    int     retcode ;
94    struct  mess_sec    *msg_sec ;
95   
96    sprintf(logmessage,"bbftpd version %s",VERSION) ;
97#ifndef WORDS_BIGENDIAN
98    msglen = ntohl(msglen) ;
99#endif
100    /*
101    ** First allocate the buffer
102    */
103    if ( (receive_buffer = (char *) malloc (msglen+1)) == NULL ) {
104        syslog(BBFTPD_ERR,"Error allocation memory for receive_buffer (bbftpd_private_receive_connection) ") ;
105        strcat(logmessage," : Error allocation memory for receive_buffer") ;
106        reply(MSG_BAD,logmessage) ;
107        return -1 ;
108    }
109    if ( (retcode = readmessage(incontrolsock,receive_buffer,msglen,recvcontrolto)) < 0 ) {
110        FREE(receive_buffer) ;
111        /*
112        ** Error ...
113        */
114        return(retcode) ;
115    }
116    msg_sec = (struct mess_sec *)receive_buffer ;
117    if ( msg_sec->crtype ==  CRYPT_RSA_PKCS1_OAEP_PADDING) {
118#ifndef WORDS_BIGENDIAN
119        lenkey = ntohl(msg_sec->pubkeylen) ;
120        lenexpo = ntohl(msg_sec->expolen) ;
121#else
122        lenkey = msg_sec->pubkeylen ;
123        lenexpo = msg_sec->expolen ;
124#endif
125        pubkey  = (unsigned char *)receive_buffer  + CRYPTMESSLEN ;
126        pubexponent = pubkey + lenkey ;
127        if ( (hisrsa = RSA_new()) == NULL) {
128            FREE(receive_buffer) ;
129            syslog(BBFTPD_ERR,"Error RSA_new (bbftpd_private_receive_connection) ") ;
130            strcat(logmessage," : RSA Error") ;
131            reply(MSG_BAD,logmessage) ;
132            return -1 ;
133        }
134        /*
135        ** Getting BIGNUM structures to store the key and exponent
136        */
137        if ( (hisrsa->n = BN_new()) == NULL) {
138            FREE(receive_buffer) ;
139            syslog(BBFTPD_ERR,"Error BN_new (bbftpd_private_receive_connection) ") ;
140            strcat(logmessage," : RSA Error") ;
141            reply(MSG_BAD,logmessage) ;
142            return -1 ;
143        }
144        if ( (hisrsa->e = BN_new()) == NULL) { 
145            FREE(receive_buffer) ;
146            syslog(BBFTPD_ERR,"Error BN_new (bbftpd_private_receive_connection) ") ;
147            strcat(logmessage," : RSA Error") ;
148            reply(MSG_BAD,logmessage) ;
149            return -1 ;
150        }
151        /*
152        ** Copy the key and exponent received
153        */
154        if ( BN_mpi2bn(pubkey,lenkey,hisrsa->n) == NULL ) {
155            FREE(receive_buffer) ;
156            syslog(BBFTPD_ERR,"Error BN_mpi2bn (bbftpd_private_receive_connection) ") ;
157            strcat(logmessage," : RSA Error") ;
158            reply(MSG_BAD,logmessage) ;
159            return -1 ;
160        }
161        if ( BN_mpi2bn(pubexponent,lenexpo,hisrsa->e) == NULL ) {
162            FREE(receive_buffer) ;
163            syslog(BBFTPD_ERR,"Error BN_mpi2bn (bbftpd_private_receive_connection) ") ;
164            strcat(logmessage," : RSA Error") ;
165            reply(MSG_BAD,logmessage) ;
166            return -1 ;
167        }
168    } else {
169        syslog(BBFTPD_ERR,"Unkwown encryption %d",msg_sec->crtype) ;
170        strcat(logmessage," : Unknown encryption") ;
171        reply(MSG_BAD,logmessage) ;
172        return -1 ;
173    }
174    /*
175    ** Now give hand to user routine
176    */
177    if ( bbftpd_private_auth(logmessage) < 0 ) {
178        syslog(BBFTPD_ERR,"bbftpd_private_auth failed : %s",logmessage) ;
179        reply(MSG_BAD,logmessage) ;
180        return -1 ;
181    }
182#ifdef NDG_AUTH
183    ndg_atexit_status = NDG_INCHILD;
184#endif // NDG_AUTH
185
186    return 0 ;
187}
188/*******************************************************************************
189** bbftpd_private_send    :                                                    *
190**                                                                             *
191**      This routine is going to crypt the buffer and to send it to the server *
192**                                                                             *
193**      OUPUT variable :                                                       *
194**          logmessage :  to write the error message in case of error          *
195**                                                                             *
196**      GLOBAL VARIABLE USED :                                                 *                                                                      *
197**                                                                             *
198**      RETURN:                                                                *
199**          -1  Unrecoverable error                                            *
200**           0  OK                                                             *
201**                                                                             *
202*******************************************************************************/
203int bbftpd_private_send(char *buffertosend, int buffertosendlength, char *logmessage)
204{
205    int     lenrsa ;
206    int     nbpackets ;
207    char    minbuffer[MINMESSLEN] ;
208    struct  message     *msg ;
209    struct  mess_private    *msg_private ;
210    char    privatebuffer[PRIVRSAMESSLEN] ;
211    char    *strtocrypt ;
212    int     lentocrypt ;
213    int     i ;
214   
215    /*
216    ** Minimum check
217    */
218    if ( buffertosendlength <=0 ) {
219        sprintf(logmessage,"buffertosendlength has to be > 0") ;
220        return -1 ;
221    } 
222    /*
223    ** First get the RSA length
224    */
225    lenrsa = RSA_size(hisrsa) ;
226    /*
227    ** Calculate the number of encrypted packets
228    ** we are going to send
229    */
230    nbpackets = buffertosendlength/(lenrsa - 42) ;
231    if (  buffertosendlength - (nbpackets*(lenrsa - 42)) != 0 ) nbpackets++ ;
232    /*
233    ** So the total length to send is nbpackets*PRIVRSAMESSLEN+MINMESSLEN
234    */
235    msg = (struct message *)minbuffer ;
236    msg->code = MSG_PRIV_DATA ;
237#ifndef WORDS_BIGENDIAN
238    msg->msglen = ntohl(nbpackets*PRIVRSAMESSLEN) ;
239#else
240    msg->msglen = nbpackets*PRIVRSAMESSLEN ;
241#endif
242    if ( writemessage(outcontrolsock,minbuffer,MINMESSLEN,recvcontrolto) < 0) {
243        sprintf(logmessage,"Error sending data") ;
244        return -1 ;
245    }
246    /*
247    ** loop on packets
248    */
249    msg_private = ( struct mess_private *) privatebuffer ;
250    strtocrypt = buffertosend ;
251    lentocrypt = lenrsa - 42 ;
252    for (i=1; i<= nbpackets ; i++ ) {
253        if ( i == nbpackets ) {
254            lentocrypt = buffertosendlength - ((nbpackets-1)*(lenrsa - 42)) ;
255        }
256        if ( (msg_private->lengthdata = RSA_public_encrypt(lentocrypt,(unsigned char *)strtocrypt,msg_private->cryptdata,hisrsa,RSA_PKCS1_OAEP_PADDING)) < 0 ) {
257            sprintf(logmessage,"Error crypting message : %s ",(char *) ERR_error_string(ERR_get_error(),NULL)) ;
258            return -1 ;
259        }
260#ifndef WORDS_BIGENDIAN
261        msg_private->lengthdata = ntohl(msg_private->lengthdata) ;
262#endif
263        if ( writemessage(outcontrolsock,privatebuffer,PRIVRSAMESSLEN,recvcontrolto) < 0) {
264            sprintf(logmessage,"Error sending encrypted data") ;
265            return -1 ;
266        }
267        strtocrypt = strtocrypt + lentocrypt ;
268    }
269    return 0 ;
270}
271/*******************************************************************************
272** bbftpd_private_recv :                                                       *
273**                                                                             *
274**      This routine is going get a message, decrypt it and fill the buffer    *
275**                                                                             *
276**      OUPUT variable :                                                       *
277**          logmessage :  to write the error message in case of error          *
278**                                                                             *
279**      GLOBAL VARIABLE USED :                                                 *                                                                      *
280**                                                                             *
281**      RETURN:                                                                *
282**          -1  Unrecoverable error                                            *
283**           >0 Number of bytes received                                       *
284**                                                                             *
285*******************************************************************************/
286int bbftpd_private_recv(char *buffertorecv, int lengthtorecv, char *logmessage)
287{
288    char    minbuffer[MINMESSLEN] ;
289    struct  message     *msg ;
290    struct  mess_private    *msg_private ;
291    char    privatebuffer[PRIVRSAMESSLEN] ;
292    char    tempbuffer[PRIVRSAMESSLEN] ;
293    int     code ;
294    int     msglen ;
295    int     expectedpackets ;
296    int      i ;
297    int     lentodecrypt ;
298    int     lendecrypted, totallendecrypted ;
299    char    *tostore ;
300
301    totallendecrypted = 0 ;
302    tostore = buffertorecv ;
303    /*
304    ** Now wait for the MSG_PRIV_DATA
305    */
306    if ( readmessage(incontrolsock,minbuffer,MINMESSLEN,recvcontrolto) < 0 ) {
307        sprintf(logmessage,"Error reading data ") ;
308        return -1 ;
309    }
310    msg = (struct message *) minbuffer ;
311    code = msg->code ;
312    if (  code != MSG_PRIV_DATA ) {
313        sprintf(logmessage,"Incorrect message header") ;
314        return -1 ;
315    } 
316#ifndef WORDS_BIGENDIAN
317    msglen = ntohl(msg->msglen) ;
318#else
319    msglen = msg->msglen ;
320#endif
321    expectedpackets = msglen/PRIVRSAMESSLEN ;
322    if ( msglen != (PRIVRSAMESSLEN * expectedpackets ) ) {
323        sprintf(logmessage,"Incorrect message length ") ;
324        return -1 ;
325    }
326    msg_private = (struct  mess_private *) privatebuffer ;
327    for ( i = 1 ; i <= expectedpackets ; i++ ) {
328        if ( readmessage(incontrolsock,privatebuffer,PRIVRSAMESSLEN,recvcontrolto) < 0 ) {
329            sprintf(logmessage,"Error reading encrypted data") ;
330            return -1 ;
331        }
332#ifndef WORDS_BIGENDIAN
333        lentodecrypt = ntohl(msg_private->lengthdata) ;
334#else
335        lentodecrypt = msg_private->lengthdata ;
336#endif
337        lendecrypted = RSA_private_decrypt(lentodecrypt,msg_private->cryptdata,(unsigned char *)tempbuffer,myrsa,RSA_PKCS1_OAEP_PADDING) ;
338        if ( totallendecrypted + lendecrypted > lengthtorecv) {
339            sprintf(logmessage,"Too much data (max=%d, receive=%d)",lengthtorecv,totallendecrypted+lendecrypted) ;
340            return -1;
341        }
342        memcpy(tostore,tempbuffer,lendecrypted) ;
343        tostore =  tostore + lendecrypted ;
344        totallendecrypted = totallendecrypted + lendecrypted ;
345    }
346    buffertorecv[totallendecrypted] = '\0' ;
347    return totallendecrypted ;
348}
349
350
351#ifdef NDG_AUTH
352/*
353** bbftpd_private_initialise :
354**
355**      Routine to initialise the private authentication infrastructure.
356**      This function is mainly a wrapper around bbftpd_private_init(),
357**      except that it also sets up an atexit function.
358*/
359int bbftpd_private_initialise(char *logmessage) {
360
361    if (atexit(bbftpd_private_atexit) != 0) {
362      sprintf(logmessage, "atexit failure");
363      return -1;
364    }
365    ndg_atexit_status = NDG_INFATHER;
366    return bbftpd_private_init(logmessage);
367}
368
369/*
370** bbftpd_private_atexit :
371**
372**      Routine to be registered with atexit() for cleaning up the private authentication
373**      infrastructure.  This function must know whether the server is in a connected or
374**      unconnected state, therefore the global variable ndg_atexit_status is used.
375*/
376void bbftpd_private_atexit(void)
377{
378  if (ndg_atexit_status == NDG_INFATHER) {
379    bbftpd_private_finalise();
380  }
381  else if (ndg_atexit_status == NDG_INCHILD) {
382    bbftpd_private_auth_finalise();
383  }
384  else {
385    syslog(BBFTPD_ERR, "ndg_atexit_status unrecognised: %d", ndg_atexit_status);
386    fprintf(stderr, "ndg_atexit_status unrecognised: %d", ndg_atexit_status);
387  }
388}
389#endif // NDG_AUTH
Note: See TracBrowser for help on using the repository browser.