00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdio.h>
00010 #include <ctype.h>
00011 #include "conv-ccs.h"
00012 #include "ccs-server.h"
00013 #include "ccs-auth.h"
00014
00015 #if CMK_CCS_AVAILABLE
00016
00017
00018
00019 struct CcsSecMan;
00020 typedef int (*CcsSecMan_allowFn)
00021 (struct CcsSecMan *self,CcsSecAttr *attr);
00022 typedef CcsSec_secretKey * (*CcsSecMan_getKeyFn)
00023 (struct CcsSecMan *self,CcsSecAttr *attr);
00024
00025 typedef struct CcsSecMan {
00026 CcsSecMan_allowFn allowRequest;
00027 CcsSecMan_getKeyFn getKey;
00028 CcsSec_secretKey * keys[256];
00029 } CcsSecMan;
00030
00031
00032
00033 typedef struct {
00034 int nClients;
00035 int *clients;
00036 CCS_RAND_state rand;
00037 } CCS_AUTH_clients;
00038
00039 static void CCS_AUTH_new(CCS_AUTH_clients *cl)
00040 {
00041 cl->nClients=0;
00042 cl->clients=NULL;
00043 CCS_RAND_new(&cl->rand);
00044 }
00045 static int CCS_AUTH_numClients(CCS_AUTH_clients *cl) {
00046 return cl->nClients;
00047 }
00048 static int CCS_AUTH_addClient(CCS_AUTH_clients *cl) {
00049 int clientNo=cl->nClients++;
00050 if ((clientNo%64)==0)
00051 cl->clients=(int*)realloc(cl->clients,sizeof(int)*(cl->nClients+63));
00052 cl->clients[clientNo]=CCS_RAND_next(&cl->rand);
00053 return clientNo;
00054 }
00055 static int CCS_AUTH_clientSalt(CCS_AUTH_clients *cl,int clientNo) {
00056 return cl->clients[clientNo];
00057 }
00058 static void CCS_AUTH_advanceSalt(CCS_AUTH_clients *cl,int clientNo) {
00059 cl->clients[clientNo]++;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068 static void CcsServer_writeReply(SOCKET fd,
00069 CcsSecMan *security,
00070 CcsSecAttr *attr,
00071 int replyLen,char *reply)
00072 {
00073 const void *bufs[3]; int lens[3]; int nBuffers=0;
00074 struct {
00075 SHA1_hash_t hash;
00076 } aheader;
00077 struct {
00078 ChMessageInt_t len;
00079 } header;
00080 if (attr->auth==1)
00081 {
00082 CCS_AUTH_hash(security->getKey(security,attr),
00083 ChMessageInt(attr->replySalt),NULL,&aheader.hash);
00084 bufs[nBuffers]=&aheader; lens[nBuffers]=sizeof(aheader); nBuffers++;
00085 }
00086
00087 header.len=ChMessageInt_new(replyLen);
00088 bufs[nBuffers]=&header; lens[nBuffers]=sizeof(header); nBuffers++;
00089 bufs[nBuffers]=reply; lens[nBuffers]=replyLen; nBuffers++;
00090 if (-1==skt_sendV(fd,nBuffers,bufs,lens)) return;
00091 skt_close(fd);
00092 #undef n
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 static const char *CcsServer_createSalt(SOCKET fd,CCS_AUTH_clients *cl,
00111 CcsSecMan *security,CcsSecAttr *attr)
00112 {
00113 ChMessageInt_t s1;
00114 ChMessageInt_t s2=ChMessageInt_new(CCS_RAND_next(&cl->rand));
00115 SHA1_hash_t s2hash;
00116 int clientId;
00117 struct {
00118 SHA1_hash_t s1hash;
00119 ChMessageInt_t clientId;
00120 ChMessageInt_t clientSalt;
00121 } reply;
00122 if (-1==skt_recvN(fd,&s1,sizeof(s1))) return "ERROR> CreateSalt challenge recv";
00123 if (-1==skt_sendN(fd,&s2,sizeof(s2))) return "ERROR> CreateSalt challenge send";
00124 if (-1==skt_recvN(fd,&s2hash,sizeof(s2hash))) return "ERROR> CreateSalt reply recv";
00125 if (CCS_AUTH_differ(security->getKey(security,attr),ChMessageInt(s2),
00126 NULL,&s2hash))
00127 return "ERROR> CreateSalt client hash mismatch! (bad password?)";
00128 CCS_AUTH_hash(security->getKey(security,attr),ChMessageInt(s1),
00129 NULL,&reply.s1hash);
00130 clientId=CCS_AUTH_addClient(cl);
00131 reply.clientId=ChMessageInt_new(clientId);
00132 reply.clientSalt=ChMessageInt_new(CCS_AUTH_clientSalt(cl,clientId));
00133 if (-1==skt_sendN(fd,&reply,sizeof(reply))) return "ERROR> CreateSalt reply send";
00134
00135
00136
00137
00138 return "Created new client";
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 static const char *CcsServer_SHA1_message(SOCKET fd,CCS_AUTH_clients *cl,
00150 CcsSecMan *security,CcsSecAttr *attr,
00151 CcsMessageHeader *hdr)
00152 {
00153 ChMessageInt_t clientNo_net;
00154 int clientNo;
00155 unsigned int salt;
00156 SHA1_hash_t hash;
00157
00158
00159 if (-1==skt_recvN(fd,&clientNo_net,sizeof(clientNo_net)))
00160 return "ERROR> During recv. client number";
00161 if (-1==skt_recvN(fd,&attr->replySalt,sizeof(attr->replySalt)))
00162 return "ERROR> During recv. reply salt";
00163 if (-1==skt_recvN(fd,&hash,sizeof(hash)))
00164 return "ERROR> During recv. authentication hash";
00165 if (-1==skt_recvN(fd,hdr,sizeof(CcsMessageHeader)))
00166 return "ERROR> During recv. message header";
00167 clientNo=ChMessageInt(clientNo_net);
00168
00169 if (clientNo<0 || clientNo>=CCS_AUTH_numClients(cl))
00170 return "ERROR> Bad client number in SHA-1 request!";
00171 salt=CCS_AUTH_clientSalt(cl,clientNo);
00172
00173
00174 if (CCS_AUTH_differ(security->getKey(security,attr),salt,
00175 hdr,&hash))
00176 return "ERROR> Authentication hash code MISMATCH-- bad or faked key";
00177
00178 CCS_AUTH_advanceSalt(cl,clientNo);
00179 return NULL;
00180 }
00181
00182
00183
00184
00185 static const char *CcsServer_readHeader(SOCKET fd,CCS_AUTH_clients *cl,
00186 CcsSecMan *security,
00187 CcsSecAttr *attr,CcsMessageHeader *hdr)
00188 {
00189
00190 unsigned char len[4];
00191 if (-1==skt_recvN(fd,&len[0],sizeof(len)))
00192 return "ERROR> During recv. length";
00193
00194
00195
00196
00197 if (len[0]<0x20)
00198 {
00199 attr->auth=0;
00200 attr->level=0;
00201 attr->replySalt=ChMessageInt_new(0);
00202 if (!security->allowRequest(security,attr))
00203 return "ERROR> Unauthenticated request denied at security check";
00204
00205 hdr->len=*(ChMessageInt_t *)len;
00206 if (-1==skt_recvN(fd,&hdr->pe,sizeof(hdr->pe)))
00207 return "ERROR> During recv. PE";
00208 if (-1==skt_recvN(fd,&hdr->handler[0],sizeof(hdr->handler)))
00209 return "ERROR> During recv. handler name";
00210 return NULL;
00211 }
00212 else if (len[0]==0x80)
00213 {
00214 if (len[1]!=0x00)
00215 return "ERROR> Bad SHA-1 version field!";
00216 attr->auth=1;
00217 attr->level=len[3];
00218 if (!security->allowRequest(security,attr))
00219 return "ERROR> Authenticated request denied at security check";
00220
00221 switch(len[2]) {
00222 case 0x00:
00223 return CcsServer_SHA1_message(fd,cl,security,attr,hdr);
00224 case 0x01:
00225 return CcsServer_createSalt(fd,cl,security,attr);
00226 default:
00227 return "ERROR> Bad SHA-1 request field!";
00228 };
00229 }
00230 else
00231 return "ERROR> Unknown authentication protocol";
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 static int allowRequest_default
00241 (struct CcsSecMan *self,CcsSecAttr *attr)
00242 {
00243 if (attr->auth==0)
00244 {
00245 return NULL==self->keys[0];
00246 } else {
00247
00248 return NULL!=self->keys[attr->level];
00249 }
00250 }
00251
00252 static CcsSec_secretKey *getKey_default
00253 (struct CcsSecMan *self,CcsSecAttr *attr)
00254 {
00255 return self->keys[attr->level];
00256 }
00257
00258 static void CcsSecMan_make_otp(const char *str,CcsSec_secretKey *key)
00259 {
00260 int i;
00261 CCS_RAND_state state;
00262 CCS_RAND_new(&state);
00263 i=0;
00264 while (str[i]!=0 && i<sizeof(state)) {
00265 state.state[i] ^= str[i];
00266 i++;
00267 }
00268 for (i=0;i<sizeof(key->data)/sizeof(int);i++) {
00269 unsigned int cur=CCS_RAND_next(&state);
00270 key->data[4*i+0]=(unsigned char)(cur>>24);
00271 key->data[4*i+1]=(unsigned char)(cur>>16);
00272 key->data[4*i+2]=(unsigned char)(cur>> 8);
00273 key->data[4*i+3]=(unsigned char)(cur>> 0);
00274 }
00275 }
00276
00277 static void CcsSecMan_printkey(FILE *out,int level,CcsSec_secretKey *k)
00278 {
00279 int i;
00280 fprintf(out,"CCS_OTP_KEY> Level %d key: ",level);
00281 for (i=0;i<sizeof(k->data);i++)
00282 fprintf(out,"%02X",k->data[i]);
00283 fprintf(out,"\n");
00284 }
00285
00286 static CcsSecMan *CcsSecMan_default(const char *authFile)
00287 {
00288 int i;
00289 FILE *secFile;
00290 char line[200];
00291 CcsSecMan *ret=(CcsSecMan *)malloc(sizeof(CcsSecMan));
00292 ret->allowRequest=allowRequest_default;
00293 ret->getKey=getKey_default;
00294 for (i=0;i<256;i++) {
00295 ret->keys[i]=NULL;
00296 }
00297 if (authFile==NULL) return ret;
00298 secFile=fopen(authFile,"r");
00299 if (secFile==NULL) {
00300 fprintf(stderr,"CCS ERROR> Cannot open CCS authentication file '%s'!\n",
00301 authFile);
00302 exit(1);
00303 }
00304 while (NULL!=fgets(line,200,secFile)) {
00305 int level;
00306 char key[200];
00307 int nItems=sscanf(line,"%d%s",&level,key);
00308 if (nItems==2 && level>=0 && level<255) {
00309
00310 CcsSec_secretKey *k=(CcsSec_secretKey *)malloc(sizeof(CcsSec_secretKey));
00311 memset(k->data,0,sizeof(CcsSec_secretKey));
00312 if (isxdigit(key[0]) && isxdigit(key[1]))
00313 CCS_AUTH_makeSecretKey(key,k);
00314 else if (0==strncmp("OTP",key,3)) {
00315 FILE *keyDest=stdout;
00316 CcsSecMan_make_otp(&key[3],k);
00317 CcsSecMan_printkey(keyDest,level,k);
00318 }
00319 else {
00320 fprintf(stderr,"CCS ERROR> Cannot parse key '%s' for level %d from CCS security file '%s'!\n",
00321 key,level,authFile);
00322 exit(1);
00323 }
00324 ret->keys[level]=k;
00325 }
00326 }
00327 fclose(secFile);
00328 return ret;
00329 }
00330
00331
00332 #define CCSDBG(x)
00333
00334
00335
00336
00337 static SOCKET ccs_server_fd=SOCKET_ERROR;
00338 static CCS_AUTH_clients ccs_clientlist;
00339 static CcsSecMan *security;
00340
00341
00342
00343
00344 void CcsServer_new(skt_ip_t *ret_ip,int *use_port,const char *authFile)
00345 {
00346 char ip_str[200];
00347 skt_ip_t ip;
00348 unsigned int port=0;if (use_port!=NULL) port=*use_port;
00349
00350 CCS_AUTH_new(&ccs_clientlist);
00351 security=CcsSecMan_default(authFile);
00352 skt_init();
00353 ip=skt_my_ip();
00354 ccs_server_fd=skt_server(&port);
00355 printf("ccs: %s\nccs: Server IP = %s, Server port = %u $\n",
00356 CMK_CCS_VERSION, skt_print_ip(ip_str,ip), port);
00357 fflush(stdout);
00358 if (ret_ip!=NULL) *ret_ip=ip;
00359 if (use_port!=NULL) *use_port=port;
00360 }
00361
00362
00363
00364
00365 SOCKET CcsServer_fd(void) {return ccs_server_fd;}
00366
00367
00368
00369
00370
00371
00372 static int req_abortFn(SOCKET skt, int code, const char *msg) {
00373
00374 fprintf(stderr,"CCS ERROR> Socket abort during request-- ignoring\n");
00375 return -1;
00376 }
00377
00378 static int CcsServer_recvRequestData(SOCKET fd,
00379 CcsImplHeader *hdr,void **reqData)
00380 {
00381 CcsMessageHeader req;
00382 int reqBytes, numPes, destPE;
00383 const char *err;
00384 if (NULL!=(err=CcsServer_readHeader(fd,&ccs_clientlist,security,
00385 &hdr->attr,&req)))
00386 {
00387 fprintf(stdout,"CCS %s\n",err);
00388 return 0;
00389 }
00390
00391
00392 strncpy(hdr->handler,req.handler,CCS_MAXHANDLER);
00393 hdr->pe=req.pe;
00394 hdr->len=req.len;
00395 hdr->replyFd=ChMessageInt_new(fd);
00396
00397
00398 numPes = 0;
00399 destPE = ChMessageInt(hdr->pe);
00400 if (destPE < -1) numPes = -destPE;
00401
00402
00403 reqBytes=ChMessageInt(req.len) + numPes*sizeof(ChMessageInt_t);
00404 *reqData=(char *)malloc(reqBytes);
00405 if (-1==skt_recvN(fd,*reqData,reqBytes)) {
00406 fprintf(stdout,"CCS ERROR> Retrieving %d message bytes\n",reqBytes);
00407 free(*reqData);
00408 return 0;
00409 }
00410 return 1;
00411 }
00412
00413 int CcsServer_recvRequest(CcsImplHeader *hdr,void **reqData)
00414 {
00415 char ip_str[200];
00416 skt_ip_t ip;
00417 unsigned int port,ret=1;
00418 SOCKET fd;
00419 skt_abortFn old=skt_set_abort(req_abortFn);
00420
00421 CCSDBG(("CCS Receiving connection...\n"));
00422 fd=skt_accept(ccs_server_fd,&ip,&port);
00423
00424 CCSDBG(("CCS Connected to IP=%s, port=%d...\n",skt_print_ip(ip_str,ip),port));
00425 hdr->attr.ip=ip;
00426 hdr->attr.port=ChMessageInt_new(port);
00427
00428 if (0==CcsServer_recvRequestData(fd,hdr,reqData))
00429 {
00430 fprintf(stdout,"During CCS Client IP:port (%s:%d) processing.\n",
00431 skt_print_ip(ip_str,ip),
00432 port);
00433 skt_close(fd);
00434 ret=0;
00435 }
00436
00437 CCSDBG(("CCS Got all %d data bytes for request.\n",reqBytes));
00438 skt_set_abort(old);
00439
00440 return ret;
00441 }
00442
00443 static int reply_abortFn(SOCKET skt, int code, const char *msg) {
00444
00445 fprintf(stderr,"CCS ERROR> Socket abort during reply-- ignoring\n");
00446 return -1;
00447 }
00448
00449
00450
00451
00452
00453 void CcsServer_sendReply(CcsImplHeader *hdr,int repBytes,const void *repData)
00454 {
00455 int fd=ChMessageInt(hdr->replyFd);
00456 skt_abortFn old;
00457 if (ChMessageInt(hdr->len)==0) {
00458 CCSDBG(("CCS Closing reply socket without a reply.\n"));
00459 skt_close(fd);
00460 return;
00461 }
00462 old=skt_set_abort(reply_abortFn);
00463 CCSDBG(("CCS Sending %d bytes of reply data\n",repBytes));
00464 CcsServer_writeReply(fd,security,&hdr->attr,repBytes,(char *)repData);
00465 skt_close(fd);
00466 CCSDBG(("CCS Reply socket closed.\n"));
00467 skt_set_abort(old);
00468 }
00469
00470
00471
00472
00473
00474
00475 #define REDIRECT_STDIO "redirect stdio"
00476 #define FETCH_STDIO "fetch stdio"
00477 char *stdio_buffer = NULL;
00478 int stdio_size = 0;
00479 int stdio_alloc = 0;
00480 int stdio_waiting = 0;
00481 CcsImplHeader stdio_waiting_hdr;
00482
00483 void write_stdio_duplicate(char* data) {
00484 if (stdio_alloc > 0) {
00485 int size = strlen(data);
00486
00487 if (stdio_waiting) {
00488 stdio_waiting = 0;
00489 CcsServer_sendReply(&stdio_waiting_hdr,size+1,data);
00490 }
00491 else {
00492 if (size+stdio_size >= stdio_alloc) {
00493 char *newbuf;
00494 stdio_alloc += (size>4096 ? size : 4096);
00495 newbuf = (char*)malloc(stdio_alloc);
00496 memcpy(newbuf, stdio_buffer, stdio_size);
00497 free(stdio_buffer);
00498 stdio_buffer = newbuf;
00499 }
00500 strcpy(&stdio_buffer[stdio_size], data);
00501 stdio_size += size;
00502 }
00503 }
00504 }
00505
00506 int check_stdio_header(CcsImplHeader *hdr) {
00507 if (strncmp(REDIRECT_STDIO, hdr->handler, strlen(REDIRECT_STDIO))==0) {
00508
00509 if (stdio_alloc == 0) {
00510 stdio_alloc = 4096;
00511 stdio_buffer = (char*)malloc(stdio_alloc);
00512 }
00513 CcsServer_sendReply(hdr,0,0);
00514 }
00515 else if (strncmp(FETCH_STDIO, hdr->handler, strlen(FETCH_STDIO))==0) {
00516
00517 if (stdio_size > 0) {
00518 hdr->len = ChMessageInt_new(1);
00519 CcsServer_sendReply(hdr,stdio_size,stdio_buffer);
00520 stdio_size = 0;
00521 } else {
00522 if (stdio_waiting) {
00523 CcsServer_sendReply(&stdio_waiting_hdr,0,0);
00524 }
00525 stdio_waiting = 1;
00526 stdio_waiting_hdr = *hdr;
00527 stdio_waiting_hdr.len = ChMessageInt_new(1);
00528 }
00529 } else {
00530 return 0;
00531 }
00532 return 1;
00533 }
00534
00535 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
00536 #if CMK_BIGSIM_CHARM
00537 #define MAX_PRINT_BUF_SIZE 1024
00538 #else
00539 #define MAX_PRINT_BUF_SIZE 8192
00540 #endif
00541 int print_fw_handler_idx;
00542
00543
00544
00545
00546 void print_fw_handler(char *msg) {
00547 write_stdio_duplicate(msg+CmiReservedHeaderSize);
00548 }
00549
00550
00551 void print_node0(const char *format, va_list args) {
00552 char buffer[MAX_PRINT_BUF_SIZE];
00553 int len;
00554 if ((len=vsnprintf(buffer, MAX_PRINT_BUF_SIZE, format, args)) >= MAX_PRINT_BUF_SIZE) CmiAbort("CmiPrintf: printing buffer too long\n");
00555 if (CmiMyPe() == 0) {
00556
00557 write_stdio_duplicate(buffer);
00558 } else {
00559
00560 char* msg = (char *)CmiAlloc(CmiReservedHeaderSize+len+1);
00561 memcpy(msg+CmiReservedHeaderSize, buffer, len+1);
00562 CmiSetHandler(msg,print_fw_handler_idx);
00563 CmiSyncSendAndFree(0,CmiReservedHeaderSize+len+1,msg);
00564 }
00565 }
00566 #endif
00567
00568 #endif
00569
00570