1 /*
2  *      $Id: sapi.c 1039 2009-01-07 19:38:08Z aaron $
3  */
4 /************************************************************************
5  *                                                                      *
6  *                             Copyright (C)  2002                      *
7  *                                Internet2                             *
8  *                             All Rights Reserved                      *
9  *                                                                      *
10  ************************************************************************/
11 /*
12  *        File:         sapi.c
13  *
14  *        Author:       Anatoly Karp
15  *                      Jeff W. Boote
16  *                      Internet2
17  *
18  *        Date:         Sun Jun 02 11:40:27 MDT 2002
19  *
20  *        Description:
21  *
22  *        This file contains the api functions typically called from an
23  *        owamp server application.
24  */
25 #include <owamp/owampP.h>
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 
33 
34 static int
OpenSocket(OWPContext ctx,int family,I2Addr addr)35 OpenSocket(
36         OWPContext  ctx,
37         int         family,
38         I2Addr      addr
39         )
40 {
41     struct addrinfo *fai;
42     struct addrinfo *ai;
43     int             on;
44     int             fd=-1;
45 
46     if( !(fai = I2AddrAddrInfo(addr,NULL,OWP_CONTROL_SERVICE_NAME))){
47         return -2;
48     }
49 
50     for(ai = fai;ai;ai = ai->ai_next){
51         if(ai->ai_family != family)
52             continue;
53 
54         fd =socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol);
55 
56         if(fd < 0)
57             continue;
58 
59         on=1;
60         if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) != 0){
61             goto failsock;
62         }
63 
64         /*
65          * TODO Check for the superseded IPV6_BINDV6ONLY sockopt too?
66          * (No - not unless someone complains.)
67          */
68 #if        defined(AF_INET6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
69         on=0;
70         if((ai->ai_family == AF_INET6) &&
71                 setsockopt(fd,IPPROTO_IPV6,IPV6_V6ONLY,&on,sizeof(on)) != 0){
72             goto failsock;
73         }
74 #endif
75 
76         if(bind(fd,ai->ai_addr,ai->ai_addrlen) == 0){
77 
78             if( !I2AddrSetSAddr(addr,ai->ai_addr,ai->ai_addrlen) ||
79                     !I2AddrSetProtocol(addr,ai->ai_protocol) ||
80                     !I2AddrSetSocktype(addr,ai->ai_socktype) ||
81                     !I2AddrSetFD(addr,fd,True)){
82                 OWPError(ctx,OWPErrFATAL,OWPErrUNKNOWN,
83                         "OpenSocket: Unable to set saddr in address record");
84                 return -1;
85             }
86 
87             break;
88         }
89 
90         if(errno == EADDRINUSE)
91             return -2;
92 
93 failsock:
94         while((close(fd) < 0) && (errno == EINTR));
95         fd = -1;
96     }
97 
98     return fd;
99 }
100 
101 /*
102  * Function:        OWPServerSockCreate
103  *
104  * Description:
105  *                 Used by server to create the initial listening socket.
106  *                 (It is not required that the server use this interface,
107  *                 but it will be kept up-to-date and in sync with the
108  *                 client OWPControlOpen function. For example, both of
109  *                 these functions currently give priority to IPV6 addresses
110  *                 over IPV4.)
111  *
112  *                 The addr should be NULL for a wildcard socket, or bound to
113  *                 a specific interface using OWPAddrByNode or
114  *                 OWPAddrByAddrInfo.
115  *
116  *                 This function will create the socket, bind it, and set the
117  *                 "listen" backlog length.
118  *
119  *                 If addr is set using OWPAddrByFD, it will cause an error.
120  *                 (It doesn't really make much sense to call this function at
121  *                 all if you are going to create and bind your own socket -
122  *                 the only thing left is to call "listen"...)
123  *
124  * In Args:
125  *
126  * Out Args:
127  *
128  * Scope:
129  * Returns:
130  * Side Effect:
131  */
132 I2Addr
OWPServerSockCreate(OWPContext ctx,I2Addr addr,OWPErrSeverity * err_ret)133 OWPServerSockCreate(
134         OWPContext      ctx,
135         I2Addr          addr,
136         OWPErrSeverity  *err_ret
137         )
138 {
139     int fd = -1;
140 
141     *err_ret = OWPErrOK;
142 
143     /*
144      * AddrByFD is invalid.
145      */
146     if(addr && (I2AddrFD(addr) > -1)){
147         OWPError(ctx,OWPErrFATAL,OWPErrINVALID,
148                 "Invalid I2Addr record - fd already specified.");
149         goto error;
150     }
151 
152     /*
153      * If no addr specified, then use wildcard address.
154      */
155     if((!addr) &&
156             !(addr = I2AddrByWildcard(OWPContextErrHandle(ctx),SOCK_STREAM,
157                     OWP_CONTROL_SERVICE_NAME))){
158         goto error;
159     }
160 
161     if( !I2AddrSetPassive(addr,True)){
162         goto error;
163     }
164 
165 #ifdef        AF_INET6
166     /*
167      * First try IPv6 addrs only
168      */
169     fd = OpenSocket(ctx,AF_INET6,addr);
170 
171     /*
172      * Fall back to IPv4 addrs if necessary.
173      */
174     if(fd == -1)
175 #endif
176         fd = OpenSocket(ctx,AF_INET,addr);
177 
178     /*
179      * if we failed to find any IPv6 or IPv4 addresses... punt.
180      */
181     if(fd < 0){
182         OWPError(ctx,OWPErrFATAL,OWPErrUNKNOWN,"OWPServerSockCreate: %M");
183         goto error;
184     }
185 
186     /*
187      * We have a bound socket - set the listen backlog.
188      */
189     if(listen(fd,OWP_LISTEN_BACKLOG) < 0){
190         OWPError(ctx,OWPErrFATAL,errno,"listen(%d,%d): %s",
191                 fd,OWP_LISTEN_BACKLOG,strerror(errno));
192         goto error;
193     }
194 
195     return addr;
196 
197 error:
198     I2AddrFree(addr);
199     *err_ret = OWPErrFATAL;
200     return NULL;
201 
202 }
203 
204 /*
205  * Function:        OWPControlAccept
206  *
207  * Description:
208  *                 This function is used to initialiize the communication
209  *                 to the peer.
210  *
211  * In Args:
212  *                 connfd,connsaddr, and connsaddrlen are all returned
213  *                 from "accept".
214  *
215  * Returns:        Valid OWPControl handle on success, NULL if
216  *              the request has been rejected, or error has occurred.
217  *              Return value does not distinguish between illegal
218  *              requests, those rejected on policy reasons, or
219  *              errors encountered by the server during execution.
220  *
221  * Side Effect:
222  */
223 OWPControl
OWPControlAccept(OWPContext ctx,int connfd,struct sockaddr * connsaddr,socklen_t connsaddrlen,uint32_t mode_offered,OWPNum64 uptime,int * retn_on_intr,OWPErrSeverity * err_ret)224 OWPControlAccept(
225         OWPContext      ctx,            /* library context              */
226         int             connfd,         /* connected socket             */
227         struct sockaddr *connsaddr,     /* connected socket addr        */
228         socklen_t       connsaddrlen,   /* connected socket addr len    */
229         uint32_t        mode_offered,   /* advertised server mode       */
230         OWPNum64        uptime,         /* uptime for server            */
231         int             *retn_on_intr,  /* if *retn_on_intr return      */
232         OWPErrSeverity  *err_ret        /* err - return                 */
233         )
234 {
235     OWPControl      cntrl;
236     uint8_t         challenge[16];
237     uint8_t         salt[16];
238     uint8_t         rawtoken[64];
239     uint8_t         token[64];
240     uint8_t         *pf=NULL;
241     void            *pf_free=NULL;
242     size_t          pf_len=0;
243     int             rc;
244     OWPTimeStamp    timestart,timeend;
245     int             ival=1;
246     int             *intr = &ival;
247     char            remotenode[NI_MAXHOST],remoteserv[NI_MAXSERV];
248     size_t          remotenodelen = sizeof(remotenode);
249     size_t          remoteservlen = sizeof(remoteserv);
250     char            localnode[NI_MAXHOST],localserv[NI_MAXSERV];
251     size_t          localnodelen = sizeof(localnode);
252     size_t          localservlen = sizeof(localserv);
253 
254     if(retn_on_intr){
255         intr = retn_on_intr;
256     }
257 
258     *err_ret = OWPErrOK;
259 
260     if ( !(cntrl = _OWPControlAlloc(ctx,err_ret)))
261         goto error;
262 
263     cntrl->sockfd = connfd;
264     cntrl->server = True;
265 
266     /*
267      * set up remote_addr for policy decisions, and log reporting.
268      *
269      * If connsaddr is non-existant, than create the I2Addr using
270      * the socket.
271      */
272     if(!connsaddr || !connsaddrlen){
273         if( !(cntrl->remote_addr = I2AddrBySockFD(
274                     OWPContextErrHandle(ctx),connfd,True))){
275             goto error;
276         }
277     }
278     else{
279         if( !(cntrl->remote_addr = I2AddrBySAddr(
280                     OWPContextErrHandle(ctx),
281                     connsaddr,connsaddrlen,SOCK_STREAM,0)) ||
282                 !I2AddrSetFD(cntrl->remote_addr,connfd,True)){
283             goto error;
284         }
285     }
286 
287     /*
288      * set up local_addr for policy decisions, and log reporting.
289      */
290     if( !(cntrl->local_addr = I2AddrByLocalSockFD(
291                     OWPContextErrHandle(ctx),connfd,False))){
292         *err_ret = OWPErrFATAL;
293         goto error;
294     }
295 
296     if( !I2AddrNodeName(cntrl->remote_addr,remotenode,&remotenodelen) ||
297             !I2AddrServName(cntrl->remote_addr,remoteserv,&remoteservlen) ||
298             !I2AddrNodeName(cntrl->local_addr,localnode,&localnodelen) ||
299             !I2AddrServName(cntrl->local_addr,localserv,&localservlen)){
300         goto error;
301     }
302 
303     OWPError(ctx,OWPErrINFO,OWPErrPOLICY,
304             "Connection to ([%s]:%s) from ([%s]:%s)",
305             localnode,localserv,remotenode,remoteserv);
306 
307     /* generate 16 random bytes of challenge and salt. */
308     if((I2RandomBytes(ctx->rand_src,challenge,sizeof(challenge)) != 0) ||
309             (I2RandomBytes(ctx->rand_src,salt, sizeof(salt)) != 0)){
310         *err_ret = OWPErrFATAL;
311         goto error;
312     }
313 
314     if(!OWPGetTimeOfDay(ctx,&timestart)){
315         OWPError(ctx,OWPErrFATAL,OWPErrUNKNOWN,"OWPGetTimeOfDay(): %M");
316         *err_ret = OWPErrFATAL;
317         goto error;
318     }
319     if( (rc = _OWPWriteServerGreeting(cntrl,intr,mode_offered,
320                     challenge,salt,ctx->pbkdf2_count)) < OWPErrOK){
321         *err_ret = (OWPErrSeverity)rc;
322         goto error;
323     }
324 
325     /*
326      * If no mode offered, immediately close socket after sending
327      * server greeting.
328      */
329     if(!mode_offered){
330         OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
331                 "Control request to ([%s]:%s) denied from ([%s]:%s): mode == 0",
332                 localnode,localserv,remotenode,remoteserv);
333         goto error;
334     }
335 
336     if((rc = _OWPReadSetupResponse(cntrl,intr,&cntrl->mode,rawtoken,
337                     cntrl->readIV)) < OWPErrOK){
338         *err_ret = (OWPErrSeverity)rc;
339         goto error;
340     }
341 
342     if(!OWPGetTimeOfDay(ctx,&timeend)){
343         OWPError(ctx,OWPErrFATAL,OWPErrUNKNOWN,"OWPGetTimeOfDay(): %M");
344         *err_ret = OWPErrFATAL;
345         goto error;
346     }
347     cntrl->rtt_bound = OWPNum64Sub(timeend.owptime,timestart.owptime);
348 
349     /* insure that exactly one mode is chosen */
350     if((cntrl->mode != OWP_MODE_OPEN) &&
351             (cntrl->mode != OWP_MODE_AUTHENTICATED) &&
352             (cntrl->mode != OWP_MODE_ENCRYPTED)){
353         *err_ret = OWPErrFATAL;
354         goto error;
355     }
356 
357     if(!(cntrl->mode | mode_offered)){ /* can't provide requested mode */
358         OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
359                 "Control request to ([%s]:%s) denied from ([%s]:%s): mode not offered (%u)",
360                 localnode,localserv,remotenode,remoteserv,cntrl->mode);
361         if( (rc = _OWPWriteServerStart(cntrl,intr,OWP_CNTRL_REJECT,0)) <
362                 OWPErrOK){
363             *err_ret = (OWPErrSeverity)rc;
364         }
365         goto error;
366     }
367 
368     if(cntrl->mode & (OWP_MODE_AUTHENTICATED|OWP_MODE_ENCRYPTED)){
369         OWPBoolean  getkey_success;
370 
371         /*
372          * go through the motions of decrypting token even if
373          * getkey fails to find username to minimize vulnerability
374          * to timing attacks.
375          */
376         getkey_success = _OWPCallGetPF(cntrl->ctx,cntrl->userid_buffer,
377                 &pf,&pf_len,&pf_free, err_ret);
378         if(!getkey_success && (*err_ret != OWPErrOK)){
379             (void)_OWPWriteServerStart(cntrl,intr,OWP_CNTRL_FAILURE,0);
380             goto error;
381         }
382 
383         if(OWPDecryptToken(pf,pf_len,salt,ctx->pbkdf2_count,
384                     rawtoken,token) < 0){
385             OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
386                     "Encryption state problem?!?!");
387             (void)_OWPWriteServerStart(cntrl,intr,OWP_CNTRL_FAILURE,0);
388             *err_ret = OWPErrFATAL;
389             goto error;
390         }
391 
392         /* Decrypted challenge is in the first 16 bytes */
393         if((memcmp(challenge,token,16) != 0) || !getkey_success){
394             if(!getkey_success){
395                 OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
396                         "Unknown userid (%s) from ([%s]:%s)",
397                         cntrl->userid_buffer,remotenode,remoteserv);
398             }
399             else{
400                 OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
401                         "Control request to ([%s]:%s) denied from ([%s]:%s):Invalid challenge encryption",
402                         localnode,localserv,remotenode,remoteserv);
403             }
404             (void)_OWPWriteServerStart(cntrl,intr,OWP_CNTRL_REJECT,0);
405             goto error;
406         }
407 
408         /* Authentication ok - set encryption fields */
409         cntrl->userid = cntrl->userid_buffer;
410         if(I2RandomBytes(cntrl->ctx->rand_src,cntrl->writeIV,16) != 0){
411             OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
412                     "Unable to fetch randomness...");
413             (void)_OWPWriteServerStart(cntrl,intr,OWP_CNTRL_FAILURE,0);
414             goto error;
415         }
416 
417         memcpy(cntrl->aessession_key,&token[16],16);
418         _OWPMakeKey(cntrl,cntrl->aessession_key);
419 
420         memcpy(cntrl->hmac_key,&token[32],32);
421         I2HMACSha1Init(cntrl->send_hmac_ctx,cntrl->hmac_key,
422                 sizeof(cntrl->hmac_key));
423         I2HMACSha1Init(cntrl->recv_hmac_ctx,cntrl->hmac_key,
424                 sizeof(cntrl->hmac_key));
425 
426         if(pf_free){
427             /* clean-up */
428             memset(pf,0,pf_len);
429             free(pf_free);
430             pf_free = NULL;
431             pf = NULL;
432             pf_len = 0;
433         }
434     }
435 
436     if(!_OWPCallCheckControlPolicy(cntrl,cntrl->mode,cntrl->userid,
437                 I2AddrSAddr(cntrl->local_addr,NULL),
438                 I2AddrSAddr(cntrl->remote_addr,NULL),err_ret)){
439         if(*err_ret > OWPErrWARNING){
440             OWPError(ctx,OWPErrWARNING,OWPErrPOLICY,
441                     "ControlSession request to ([%s]:%s) denied from userid(%s):([%s]:%s)",
442                     localnode,localserv,
443                     (cntrl->userid)?cntrl->userid:(char*)"nil",
444                     remotenode,remoteserv);
445             /*
446              * send mode of 0 to client, and then close.
447              */
448             (void)_OWPWriteServerStart(cntrl,intr,OWP_CNTRL_REJECT,0);
449         }
450         else{
451             OWPError(ctx,*err_ret,OWPErrUNKNOWN,
452                     "Policy function failed.");
453             (void)_OWPWriteServerStart(cntrl,intr,OWP_CNTRL_FAILURE,0);
454         }
455         goto error;
456     }
457 
458     /*
459      * Made it through the gauntlet - accept the control session!
460      */
461     if( (rc = _OWPWriteServerStart(cntrl,intr,OWP_CNTRL_ACCEPT,uptime)) <
462             OWPErrOK){
463         *err_ret = (OWPErrSeverity)rc;
464         goto error;
465     }
466     OWPError(ctx,OWPErrWARNING,OWPErrPOLICY,
467             "ControlSession([%s]:%s) accepted from userid(%s):([%s]:%s)",
468             localnode,localserv,
469             (cntrl->userid)?cntrl->userid:(char*)"nil",
470             remotenode,remoteserv);
471 
472     return cntrl;
473 
474 error:
475     if(pf_free)
476         free(pf_free);
477     OWPControlClose(cntrl);
478     return NULL;
479 }
480 
481 OWPErrSeverity
OWPProcessTestRequest(OWPControl cntrl,int * retn_on_intr)482 OWPProcessTestRequest(
483         OWPControl  cntrl,
484         int         *retn_on_intr
485         )
486 {
487     OWPTestSession  tsession = NULL;
488     OWPErrSeverity  err_ret=OWPErrOK;
489     uint16_t       port;
490     int             rc;
491     OWPAcceptType   acceptval = OWP_CNTRL_FAILURE;
492     int             ival=1;
493     int             *intr = &ival;
494     struct sockaddr *rsaddr;
495     struct sockaddr *ssaddr;
496     socklen_t       saddrlen;
497 
498     if(retn_on_intr){
499         intr = retn_on_intr;
500     }
501 
502     /*
503      * Read the TestRequest and alloate tsession to hold the information.
504      */
505     if((rc = _OWPReadTestRequest(cntrl,intr,&tsession,&acceptval)) !=
506             OWPErrOK){
507         if(acceptval < 0)
508             return OWPErrFATAL;
509         return OWPErrWARNING;
510     }
511 
512     assert(tsession);
513 
514     /*
515      * Get local copies of saddr's.
516      */
517     rsaddr = I2AddrSAddr(tsession->receiver,&saddrlen);
518     ssaddr = I2AddrSAddr(tsession->sender,&saddrlen);
519     if(!rsaddr || !ssaddr){
520         OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
521                 "Invalid addresses from ReadTestRequest");
522         err_ret = OWPErrFATAL;
523         goto error;
524     }
525 
526     if(tsession->conf_receiver && (_OWPCreateSID(tsession) != 0)){
527         err_ret = OWPErrWARNING;
528         acceptval = OWP_CNTRL_FAILURE;
529         goto error;
530     }
531 
532     /*
533      * Now that we know the SID we can create the schedule
534      * context.
535      */
536     if(!(tsession->sctx = OWPScheduleContextCreate(cntrl->ctx,
537                     tsession->sid,&tsession->test_spec))){
538         OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
539                 "Unable to init schedule generator");
540         err_ret = OWPErrWARNING;
541         acceptval = OWP_CNTRL_FAILURE;
542         goto error;
543     }
544 
545     /*
546      * if conf_receiver - open port and get SID.
547      */
548     if(tsession->conf_receiver){
549         if(tsession->conf_sender){
550             /*
551              * NOTE:
552              * This implementation only configures "local" test
553              * endpoints. For a more distributed implementation
554              * where a single control server could manage multiple
555              * endpoints - this check would be removed, and
556              * conf_sender and conf_receiver could make
557              * sense together.
558              */
559             acceptval = OWP_CNTRL_UNSUPPORTED;
560             err_ret = OWPErrWARNING;
561             goto error;
562         }
563 
564         if(!_OWPCallCheckTestPolicy(cntrl,False,
565                     rsaddr,ssaddr,saddrlen,
566                     &tsession->test_spec,&tsession->closure,
567                     &err_ret)){
568             if(err_ret < OWPErrOK)
569                 goto error;
570             OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
571                     "Test not allowed");
572             acceptval = OWP_CNTRL_REJECT;
573             err_ret = OWPErrWARNING;
574             goto error;
575         }
576 
577         /* receiver first */
578         if(!_OWPEndpointInit(cntrl,tsession,tsession->receiver,NULL,
579                     &acceptval,&err_ret)){
580             goto error;
581         }
582     }
583 
584     if(tsession->conf_sender){
585         /*
586          * Check for possible DoS as advised in Section 7 of owdp
587          * spec.
588          * (control-client MUST be receiver if openmode.)
589          */
590 
591         if(!(cntrl->mode & OWP_MODE_DOCIPHER)){
592             struct sockaddr *csaddr;
593             socklen_t       csaddrlen;
594             char            remotenode[NI_MAXHOST];
595             size_t          remotenodelen = sizeof(remotenode);
596             char            recvnode[NI_MAXHOST];
597             size_t          recvnodelen = sizeof(recvnode);
598 
599             if( !(csaddr = I2AddrSAddr(cntrl->remote_addr,&csaddrlen)) ||
600                     !I2AddrNodeName(cntrl->remote_addr,remotenode,
601                         &remotenodelen) ||
602                     !I2AddrNodeName(tsession->receiver,recvnode,&recvnodelen)){
603                 OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
604                         "Unable to determine sockaddr information");
605                 err_ret = OWPErrFATAL;
606                 goto error;
607             }
608             if(I2SockAddrEqual(csaddr,csaddrlen,rsaddr,saddrlen,
609                         I2SADDR_ADDR) <= 0){
610                 OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,
611                         "Test Denied: OpenMode recieve_addr(%s) != control_client(%s)",
612                         recvnode,remotenode);
613                 acceptval = OWP_CNTRL_REJECT;
614                 err_ret = OWPErrWARNING;
615                 goto error;
616             }
617         }
618 
619         if(!_OWPCallCheckTestPolicy(cntrl,True,
620                     ssaddr,rsaddr,saddrlen,
621                     &tsession->test_spec,
622                     &tsession->closure,&err_ret)){
623             if(err_ret < OWPErrOK)
624                 goto error;
625             OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,"Test not allowed");
626             acceptval = OWP_CNTRL_REJECT;
627             err_ret = OWPErrWARNING;
628             goto error;
629         }
630         if(!_OWPEndpointInit(cntrl,tsession,tsession->sender,NULL,
631                     &acceptval,&err_ret)){
632             goto error;
633         }
634         if(!_OWPEndpointInitHook(cntrl,tsession,&acceptval,&err_ret)){
635             goto error;
636         }
637         port = I2AddrPort(tsession->sender);
638     }
639 
640     /*
641      * This portion could technically be above with the rest
642      * of the conf_receiver portion since this implementation
643      * does not currently support (conf_receiver && conf_sender),
644      * but is broken out so the logic is preserved.
645      */
646     if(tsession->conf_receiver){
647         if(!_OWPEndpointInitHook(cntrl,tsession,&acceptval,&err_ret)){
648             goto error;
649         }
650         port = I2AddrPort(tsession->receiver);
651     }
652 
653     if( (rc = _OWPWriteAcceptSession(cntrl,intr,OWP_CNTRL_ACCEPT,
654                     port,tsession->sid)) < OWPErrOK){
655         err_ret = (OWPErrSeverity)rc;
656         goto err2;
657     }
658 
659     /*
660      * Add tsession to list of tests managed by this control connection.
661      */
662     tsession->next = cntrl->tests;
663     cntrl->tests = tsession;
664 
665     return OWPErrOK;
666 
667 error:
668     /*
669      * If it is a non-fatal error, communication should continue, so
670      * send negative accept.
671      */
672     if(err_ret >= OWPErrWARNING)
673         (void)_OWPWriteAcceptSession(cntrl,intr,acceptval,0,NULL);
674 
675 err2:
676     if(tsession)
677         _OWPTestSessionFree(tsession,acceptval);
678 
679     return err_ret;
680 }
681 
682 OWPErrSeverity
OWPProcessStartSessions(OWPControl cntrl,int * retn_on_intr)683 OWPProcessStartSessions(
684         OWPControl  cntrl,
685         int         *retn_on_intr
686         )
687 {
688     int             rc;
689     OWPTestSession  tsession;
690     OWPErrSeverity  err,err2=OWPErrOK;
691     int             ival=1;
692     int             *intr = &ival;
693 
694     if(retn_on_intr){
695         intr = retn_on_intr;
696     }
697 
698     if( (rc = _OWPReadStartSessions(cntrl,intr)) < OWPErrOK)
699         return _OWPFailControlSession(cntrl,rc);
700 
701     for(tsession = cntrl->tests;tsession;tsession = tsession->next){
702         if(tsession->endpoint){
703             if(!_OWPEndpointStart(tsession->endpoint,&err)){
704                 (void)_OWPWriteStartAck(cntrl,intr,
705                                         OWP_CNTRL_FAILURE);
706                 return _OWPFailControlSession(cntrl,err);
707             }
708             err2 = MIN(err,err2);
709         }
710     }
711 
712     if( (rc = _OWPWriteStartAck(cntrl,intr,OWP_CNTRL_ACCEPT)) < OWPErrOK)
713         return _OWPFailControlSession(cntrl,rc);
714 
715 
716     return err2;
717 }
718 
719 struct DoDataState{
720     OWPControl      cntrl;
721     OWPErrSeverity  err;
722     uint32_t       rec_size;
723     OWPBoolean      send;
724     uint32_t       begin;
725     uint32_t       end;
726     uint32_t       inbuf;
727     uint64_t       count;
728     uint32_t       maxiseen;
729     int             *intr;
730 };
731 
732 static int
DoDataRecords(OWPDataRec * rec,void * udata)733 DoDataRecords(
734         OWPDataRec  *rec,
735         void        *udata
736         )
737 {
738     struct DoDataState  *dstate = (struct DoDataState *)udata;
739     OWPControl          cntrl = dstate->cntrl;
740     char                *buf = (char *)cntrl->msg;
741 
742     /*
743      * Save largest index seen that is not lost.
744      * (This allows this data to be parsed again to count only those
745      * records before this index for the purposes of fetching a
746      * partial valid session even if it was unable to terminate
747      * properly.)
748      */
749     if((rec->seq_no > dstate->maxiseen) && !OWPIsLostRecord(rec)){
750         dstate->maxiseen = rec->seq_no;
751     }
752 
753     /*
754      * If this record is not in range - return 0 to continue on.
755      */
756     if((rec->seq_no < dstate->begin) || (rec->seq_no > dstate->end)){
757         return 0;
758     }
759 
760     dstate->count++;
761 
762     if(dstate->send){
763         /*
764          * Encode this record into cntrl->msg buffer.
765          */
766         if(!_OWPEncodeDataRecord(&buf[dstate->inbuf*dstate->rec_size],
767                     rec)){
768             return -1;
769         }
770         dstate->inbuf++;
771 
772         /*
773          * If the buffer is full enough to send, do so.
774          */
775         if(dstate->inbuf == _OWP_FETCH_DATAREC_BLOCKS){
776             _OWPSendHMACAdd(cntrl,buf,_OWP_FETCH_AES_BLOCKS);
777             if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,_OWP_FETCH_AES_BLOCKS,
778                         dstate->intr) != _OWP_FETCH_AES_BLOCKS){
779                 dstate->err = OWPErrFATAL;
780                 _OWPFailControlSession(cntrl,OWPErrFATAL);
781                 return -1;
782             }
783             dstate->inbuf = 0;
784         }
785         else if(dstate->inbuf > _OWP_FETCH_DATAREC_BLOCKS){
786             dstate->err = OWPErrFATAL;
787             _OWPFailControlSession(cntrl,OWPErrFATAL);
788             return -1;
789         }
790     }
791 
792     return 0;
793 }
794 
795 OWPErrSeverity
OWPProcessFetchSession(OWPControl cntrl,int * retn_on_intr)796 OWPProcessFetchSession(
797         OWPControl  cntrl,
798         int         *retn_on_intr
799         )
800 {
801     char                        *buf = (char *)cntrl->msg;
802     OWPErrSeverity              err;
803     OWPAcceptType               acceptval = OWP_CNTRL_REJECT;
804     void                        *closure = NULL;
805     struct sockaddr             *lsaddr;
806     struct sockaddr             *rsaddr;
807     socklen_t                   saddrlen;
808     uint32_t                    begin;
809     uint32_t                    end;
810     OWPSID                      sid;
811 
812     FILE                        *fp;
813     char                        fname[PATH_MAX];
814 
815     _OWPSessionHeaderInitialRec fhdr;
816     struct flock                flk;
817     int                         lock_tries=0;
818     int                         finish_tries=0;
819 
820     uint32_t                    sendrecs;
821     uint32_t                    next_seqno = 0;
822     uint32_t                    num_skiprecs = 0;
823     off_t                       tr_size;
824 
825     struct DoDataState          dodata;
826 
827     int                         ival=1;
828     int                         *intr = &ival;
829 
830     if(retn_on_intr){
831         intr = retn_on_intr;
832     }
833 
834     /*
835      * Read the complete FetchSession request.
836      */
837     if((err = _OWPReadFetchSession(cntrl,intr,&begin,&end,sid)) < OWPErrOK){
838         return _OWPFailControlSession(cntrl, err);
839     }
840 
841     lsaddr = I2AddrSAddr(cntrl->local_addr,&saddrlen);
842     rsaddr = I2AddrSAddr(cntrl->remote_addr,&saddrlen);
843     if(!_OWPCallCheckFetchPolicy(cntrl,
844                     lsaddr,rsaddr,saddrlen,begin,end,sid,&closure,&err)){
845         if(err < OWPErrOK){
846             return _OWPFailControlSession(cntrl,err);
847         }
848         OWPError(cntrl->ctx,OWPErrWARNING,OWPErrPOLICY,"Fetch not allowed");
849         goto reject;
850     }
851 
852     /*
853      * Try and open the file containing sid information.
854      */
855     if( !(fp = _OWPCallOpenFile(cntrl,closure,sid,fname))){
856         goto reject;
857     }
858 
859     /*
860      * Read the file header - fp will end up at beginning of
861      * TestRequest record.
862      */
863 read_file:
864     if( !_OWPReadDataHeaderInitial(cntrl->ctx,fp,&fhdr)){
865         OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
866                 "_OWPReadDataHeaderInitial(\"%s\"): %M",fname);
867         goto failed;
868     }
869 
870     /*
871      * Only version 3 files are supported for "fetch session"
872      * response messages.
873      */
874     if(fhdr.version != 3){
875         OWPError(cntrl->ctx,OWPErrFATAL,OWPErrINVALID,
876                 "OWPProcessFetchSession(\"%s\"): Invalid file version: %d",
877                 fname,fhdr.version);
878         goto failed;
879     }
880 
881     if(fhdr.finished == OWP_SESSION_FINISHED_ERROR){
882         OWPError(cntrl->ctx,OWPErrFATAL,OWPErrINVALID,
883                 "OWPProcessFetchSession(\"%s\"): Invalid file!",
884                 fname);
885         goto failed;
886     }
887 
888     /*
889      * If the session is not complete, then the file needs be locked before
890      * trusting headers. If num_datarecs is still 0 when it is locked, then use
891      * the filesize to determine the number of records. Read the file
892      * as is - closing the fd will automatically unlock it.
893      *
894      * If num_datarecs is set, the data up to that point can be trusted.
895      */
896     if(fhdr.finished != OWP_SESSION_FINISHED_NORMAL){
897         memset(&flk,0,sizeof(flk));
898         flk.l_start = 0;
899         flk.l_len = 0;
900         flk.l_whence = SEEK_SET;
901         flk.l_type = F_RDLCK;
902 
903         if( fcntl(fileno(fp), F_SETLK, &flk) < 0){
904             /*
905              * If there is currently a lock, go back and reread the
906              * header - hopefully the session is being finalized.
907              * (Counter here to give up after 5 tries - escalating
908              * wait times.)
909              */
910             if((errno == EACCES) || (errno == EAGAIN)){
911                 if(lock_tries > 4){
912                     OWPError(cntrl->ctx,OWPErrFATAL,errno,
913                             "Repeat lock failures: fcntl(\"%s\"): %M",fname);
914                     goto failed;
915                 }
916                 fflush(fp);
917                 sleep(1<<lock_tries);
918                 lock_tries++;
919                 goto read_file;
920             }
921 
922             /*
923              * any other error is fatal.
924              */
925             OWPError(cntrl->ctx,OWPErrFATAL,errno,
926                     "Unable to lock session file: fcntl(\"%s\"): %M",fname);
927             goto failed;
928         }
929 
930         /*
931          * Lock obtained, reread the file header.
932          */
933         if( !_OWPReadDataHeaderInitial(cntrl->ctx,fp,&fhdr)){
934             OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
935                     "_OWPReadDataHeaderInitial(\"%s\"): %M",fname);
936             goto failed;
937         }
938 
939         /*
940          * If a "complete" session was requested, and the test did not
941          * terminate normally - we MUST deny here.
942          * Add a delay in to handle possible race conditions.
943          */
944         if((begin == 0) && (end == 0xFFFFFFFF) &&
945                 (fhdr.finished != OWP_SESSION_FINISHED_NORMAL)){
946             if(finish_tries > 4){
947                 OWPError(cntrl->ctx,OWPErrFATAL,EBUSY,
948                         "OWPProcessFetchSession(\"%s\"): Request for complete session, but session not yet terminated!",
949                         fname);
950                 goto reject;
951             }
952             fflush(fp);
953 
954             // unlock the file since we'll need to retry
955             memset(&flk,0,sizeof(flk));
956             flk.l_start = 0;
957             flk.l_len = 0;
958             flk.l_whence = SEEK_SET;
959             flk.l_type = F_UNLCK;
960             fcntl(fileno(fp), F_SETLK, &flk);
961 
962             sleep(1<<finish_tries);
963             finish_tries++;
964 
965             goto read_file;
966         }
967 
968 
969         /*
970          * If the file doesn't have the number of recs set, then records
971          * continue to the end of the file.
972          */
973         if(!fhdr.num_datarecs){
974             fhdr.num_datarecs = (fhdr.sbuf.st_size - fhdr.oset_datarecs) /
975                 fhdr.rec_size;
976         }
977     }
978 
979     /*
980      * setup the state record for parsing the records.
981      */
982     dodata.cntrl = cntrl;
983     dodata.intr = intr;
984     dodata.err = OWPErrOK;
985     dodata.rec_size = fhdr.rec_size;
986     dodata.send = False;
987     dodata.begin = begin;
988     dodata.end = end;
989     dodata.inbuf = 0;
990     dodata.count = 0;
991     dodata.maxiseen = 0;
992 
993     /*
994      * Now - count the number of records that will be sent.
995      * short-cut the count if full session is requested.
996      */
997     if((fhdr.finished == OWP_SESSION_FINISHED_NORMAL) &&
998             (begin == 0) && (end == 0xFFFFFFFF)){
999         sendrecs = fhdr.num_datarecs;
1000     }
1001     else{
1002         /* forward pointer to data records for counting */
1003         if(fseeko(fp,fhdr.oset_datarecs,SEEK_SET)){
1004             OWPError(cntrl->ctx,OWPErrFATAL,errno,"fseeko(): %M");
1005             goto failed;
1006         }
1007         /*
1008          * Now, count the records in range.
1009          */
1010         if(OWPParseRecords(cntrl->ctx,fp,fhdr.num_datarecs,fhdr.version,
1011                     DoDataRecords,&dodata) != OWPErrOK){
1012             goto failed;
1013         }
1014         sendrecs = dodata.count;
1015         dodata.count = 0;
1016 
1017         /*
1018          * If the session did not complete normally, redo the
1019          * count ignoring all "missing" packets after the
1020          * last seen one.
1021          */
1022         if((fhdr.finished != OWP_SESSION_FINISHED_NORMAL) &&
1023                 (dodata.maxiseen < end)){
1024             dodata.end = dodata.maxiseen;
1025 
1026             /* set pointer to beginning of data recs */
1027             if(fseeko(fp,fhdr.oset_datarecs,SEEK_SET)){
1028                 OWPError(cntrl->ctx,OWPErrFATAL,errno,"fseeko(): %M");
1029                 goto failed;
1030             }
1031 
1032             if(OWPParseRecords(cntrl->ctx,fp,fhdr.num_datarecs,fhdr.version,
1033                         DoDataRecords,&dodata) != OWPErrOK){
1034                 goto failed;
1035             }
1036             sendrecs = dodata.count;
1037             dodata.count = 0;
1038         }
1039 
1040     }
1041 
1042     if(fhdr.finished){
1043         next_seqno = fhdr.next_seqno;
1044         num_skiprecs = fhdr.num_skiprecs;
1045     }
1046 
1047     /* set file pointer to beginning of TestReq */
1048     if(fseeko(fp,_OWP_TESTREC_OFFSET,SEEK_SET)){
1049         OWPError(cntrl->ctx,OWPErrFATAL,errno,"fseeko(): %M");
1050         goto failed;
1051     }
1052 
1053     /*
1054      * Now accept the FetchRequest.
1055      */
1056     acceptval = OWP_CNTRL_ACCEPT;
1057     if((err = _OWPWriteFetchAck(cntrl,intr,acceptval,fhdr.finished,next_seqno,
1058                     num_skiprecs,sendrecs)) < OWPErrOK){
1059         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1060         return _OWPFailControlSession(cntrl,err);
1061     }
1062 
1063     /*
1064      * Determine how large TestReq is including "slots"
1065      */
1066     if(fhdr.oset_skiprecs){
1067         tr_size = fhdr.oset_skiprecs;
1068     }
1069     else{
1070         tr_size = fhdr.oset_datarecs;
1071     }
1072 
1073     if(fhdr.oset_datarecs){
1074         tr_size = MIN(tr_size,fhdr.oset_datarecs);
1075     }
1076 
1077     tr_size -= _OWP_TESTREC_OFFSET;
1078 
1079     if(tr_size % _OWP_RIJNDAEL_BLOCK_SIZE){
1080         OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
1081                 "OWPProcessFetchSession: Invalid TestReq in file \"%s\"",
1082                 fname);
1083     }
1084 
1085     /*
1086      * Read the TestRequestPreamble from the file, modify the HMAC
1087      * then send.
1088      * TestRequestPreamble is 7 blocks long (last one is HMAC).
1089      */
1090     if(fread(buf,7*_OWP_RIJNDAEL_BLOCK_SIZE,1,fp) != 1){
1091         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1092         return _OWPFailControlSession(cntrl,OWPErrFATAL);
1093     }
1094     _OWPSendHMACAdd(cntrl,buf,6);
1095     _OWPSendHMACDigestClear(cntrl,&buf[96]);
1096     if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,7,intr) != 7){
1097         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1098         return _OWPFailControlSession(cntrl,OWPErrFATAL);
1099     }
1100     tr_size -= (_OWP_RIJNDAEL_BLOCK_SIZE*7);
1101 
1102     /*
1103      * Read the TestReq slots from the file and write it to the socket.
1104      * Ignore last block (it holds original HMAC - recompute the last
1105      * block of HMAC and send).
1106      * (after this loop - fp is positioned at hdr_off.
1107      */
1108     while(tr_size > _OWP_RIJNDAEL_BLOCK_SIZE){
1109         if(fread(buf,1,_OWP_RIJNDAEL_BLOCK_SIZE,fp) !=
1110                 _OWP_RIJNDAEL_BLOCK_SIZE){
1111             _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1112             return _OWPFailControlSession(cntrl,OWPErrFATAL);
1113         }
1114         _OWPSendHMACAdd(cntrl,buf,1);
1115         if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,1,intr) != 1){
1116             _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1117             return _OWPFailControlSession(cntrl,OWPErrFATAL);
1118         }
1119         tr_size -= _OWP_RIJNDAEL_BLOCK_SIZE;
1120     }
1121     _OWPSendHMACDigestClear(cntrl,buf);
1122     if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,1,intr) != 1){
1123         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1124         return _OWPFailControlSession(cntrl,OWPErrFATAL);
1125     }
1126 
1127     if(fhdr.finished && fhdr.num_skiprecs){
1128 
1129         /* set file pointer to beginning of skips */
1130         if(fseeko(fp,fhdr.oset_skiprecs,SEEK_SET)){
1131             OWPError(cntrl->ctx,OWPErrFATAL,errno,"fseeko(): %M");
1132             _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1133             return _OWPFailControlSession(cntrl,OWPErrFATAL);
1134         }
1135 
1136         /*
1137          * size for all skip records
1138          */
1139         tr_size = fhdr.num_skiprecs * _OWP_SKIPREC_SIZE;
1140 
1141         /*
1142          * First deal with complete blocks of skips
1143          */
1144         while(tr_size > _OWP_RIJNDAEL_BLOCK_SIZE){
1145             if(fread(buf,1,_OWP_RIJNDAEL_BLOCK_SIZE,fp) !=
1146                     _OWP_RIJNDAEL_BLOCK_SIZE){
1147                 _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1148                 return _OWPFailControlSession(cntrl,OWPErrFATAL);
1149             }
1150             _OWPSendHMACAdd(cntrl,buf,1);
1151             if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,1,intr) != 1){
1152                 _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1153                 return _OWPFailControlSession(cntrl,OWPErrFATAL);
1154             }
1155             tr_size -= _OWP_RIJNDAEL_BLOCK_SIZE;
1156         }
1157 
1158         /*
1159          * Now deal with "partial" skips
1160          */
1161         if(tr_size > 0){
1162             /* zero block so extra space will be 0 padded */
1163             memset(buf,0,_OWP_RIJNDAEL_BLOCK_SIZE);
1164 
1165             if(fread(buf,1,tr_size,fp) != (size_t)tr_size){
1166                 _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1167                 return _OWPFailControlSession(cntrl,OWPErrFATAL);
1168             }
1169             _OWPSendHMACAdd(cntrl,buf,1);
1170             if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,1,intr) != 1){
1171                 _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1172                 return _OWPFailControlSession(cntrl,OWPErrFATAL);
1173             }
1174         }
1175 
1176     }
1177 
1178     /* now send HMAC Block (between skips & data */
1179     _OWPSendHMACDigestClear(cntrl,buf);
1180     if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,1,intr) != 1){
1181         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1182         return _OWPFailControlSession(cntrl,err);
1183     }
1184 
1185 
1186     /*
1187      * Shortcut for no data.
1188      */
1189     if(!sendrecs) goto final;
1190 
1191     /* set file pointer to beginning of data */
1192     if(fseeko(fp,fhdr.oset_datarecs,SEEK_SET)){
1193         OWPError(cntrl->ctx,OWPErrFATAL,errno,"fseeko(): %M");
1194         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1195         return _OWPFailControlSession(cntrl,err);
1196     }
1197 
1198     /*
1199      * Now, send the data!
1200      */
1201     dodata.send = True;
1202     if( (OWPParseRecords(cntrl->ctx,fp,fhdr.num_datarecs,fhdr.version,
1203                     DoDataRecords,&dodata) != OWPErrOK) ||
1204             (dodata.count != sendrecs)){
1205         _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1206         return _OWPFailControlSession(cntrl,err);
1207     }
1208 
1209     if(dodata.inbuf){
1210         /*
1211          * Set "blks" to number of AES blocks that need to be sent to
1212          * hold all "leftover" records.
1213          */
1214         int blks = (dodata.inbuf*fhdr.rec_size/_OWP_RIJNDAEL_BLOCK_SIZE) + 1;
1215 
1216         /* zero out any partial data blocks */
1217         memset(&buf[dodata.inbuf*fhdr.rec_size],0,
1218                 (blks*_OWP_RIJNDAEL_BLOCK_SIZE)-
1219                 (dodata.inbuf*fhdr.rec_size));
1220 
1221         /*
1222          * Write enough AES blocks to get remaining records.
1223          */
1224         _OWPSendHMACAdd(cntrl,buf,blks);
1225         if( (_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,blks,intr) != blks)){
1226             _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_FAILURE);
1227             return _OWPFailControlSession(cntrl,err);
1228         }
1229     }
1230 
1231 final:
1232     /*
1233      * We are done reading from the file - close it.
1234      */
1235     _OWPCallCloseFile(cntrl,closure,fp,OWP_CNTRL_ACCEPT);
1236 
1237     /* now send final HMAC Block */
1238     _OWPSendHMACDigestClear(cntrl,buf);
1239     if(_OWPSendBlocksIntr(cntrl,(uint8_t *)buf,1,intr) != 1){
1240         return _OWPFailControlSession(cntrl,err);
1241     }
1242 
1243     /*
1244      * reset state to request.
1245      */
1246     cntrl->state &= ~_OWPStateFetching;
1247     cntrl->state |= _OWPStateRequest;
1248 
1249     return OWPErrOK;
1250 
1251 failed:
1252     acceptval = OWP_CNTRL_FAILURE;
1253 reject:
1254     if(fp){
1255         _OWPCallCloseFile(cntrl,closure,fp,acceptval);
1256     }
1257 
1258     if( (err = _OWPWriteFetchAck(cntrl,intr,acceptval,0,0,0,0)) < OWPErrOK){
1259         return _OWPFailControlSession(cntrl,err);
1260     }
1261 
1262     return OWPErrWARNING;
1263 
1264 }
1265