// This function taken from openvpn-2.2.1 and tidied up a bit. static int setenv_x509(X509_NAME *x509, const char *type) { int i, n; int fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME_ENTRY *ent; const char *objbuf; uint8_t *buf; char *name_expand; size_t name_expand_size; n=X509_NAME_entry_count (x509); for(i=0; i<n; ++i) { if(!(ent=X509_NAME_get_entry (x509, i)) || !(fn=X509_NAME_ENTRY_get_object(ent)) || !(val=X509_NAME_ENTRY_get_data(ent)) || (fn_nid=OBJ_obj2nid(fn))==NID_undef || !(objbuf=OBJ_nid2sn(fn_nid))) continue; buf=(uint8_t *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */ if(ASN1_STRING_to_UTF8(&buf, val)<=0) continue; name_expand_size=64+strlen(objbuf); if(!(name_expand=(char *)malloc_w(name_expand_size, __func__))) return -1; snprintf(name_expand, name_expand_size, "X509_%s_%s", type, objbuf); sanitise(name_expand); sanitise((char*)buf); setenv(name_expand, (char*)buf, 1); free (name_expand); OPENSSL_free (buf); } return 0; }
// Sanitise the given type (sub)AST, which has already been copied static void sanitise(ast_t** astp) { assert(astp != NULL); ast_t* type = *astp; assert(type != NULL); ast_clearflag(*astp, AST_FLAG_PASS_MASK); if(ast_id(type) == TK_TYPEPARAMREF) { // We have a type param reference, convert to a nominal ast_t* def = (ast_t*)ast_data(type); assert(def != NULL); const char* name = ast_name(ast_child(def)); assert(name != NULL); REPLACE(astp, NODE(TK_NOMINAL, NONE // Package name ID(name) NONE // Type args NONE // Capability NONE)); // Ephemeral return; } // Process all our children for(ast_t* p = ast_child(type); p != NULL; p = ast_sibling(p)) sanitise(&p); }
ast_t* sanitise_type(ast_t* type) { assert(type != NULL); ast_t* new_type = ast_dup(type); sanitise(&new_type); return new_type; }
static ssize_t tftp_err(int err, char *packet, char *message, char *file) { struct errmess { unsigned short op, err; char message[]; } *mess = (struct errmess *)packet; ssize_t ret = 4; char *errstr = strerror(errno); sanitise(file); mess->op = htons(OP_ERR); mess->err = htons(err); ret += (snprintf(mess->message, 500, message, file, errstr) + 1); my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message); return ret; }
static int setenv_x509_serialnumber(ASN1_INTEGER *i, const char *env) { BIO *bio_out=NULL; BUF_MEM *bptr=NULL; char tmpbuf[256]=""; if(!(bio_out=BIO_new(BIO_s_mem()))) { log_out_of_memory(__func__); return -1; } i2a_ASN1_INTEGER(bio_out, i); BIO_get_mem_ptr(bio_out, &bptr); BIO_gets(bio_out, tmpbuf, sizeof(tmpbuf)-1); BIO_free_all(bio_out); sanitise(tmpbuf); setenv(env, (char*)tmpbuf, 1); return 0; }
static int setenv_x509_date(ASN1_TIME *tm, const char *env) { BIO *bio_out=NULL; BUF_MEM *bptr=NULL; char tmpbuf[256]=""; if(!(bio_out=BIO_new(BIO_s_mem()))) { log_out_of_memory(__func__); return -1; } ASN1_TIME_print(bio_out, tm); BIO_get_mem_ptr(bio_out, &bptr); BIO_gets(bio_out, tmpbuf, sizeof(tmpbuf)-1); BIO_free_all(bio_out); sanitise(tmpbuf); setenv(env, (char*)tmpbuf, 1); return 0; }
/* put on queue to be sent to script and deleted */ transfer->next = daemon->tftp_done_trans; daemon->tftp_done_trans = transfer; } continue; } } up = &transfer->next; } } static void free_transfer(struct tftp_transfer *transfer) { close(transfer->sockfd); if (transfer->file && (--transfer->file->refcount) == 0) { close(transfer->file->fd); free(transfer->file); } free(transfer); } static char *next(char **p, char *end) { char *ret = *p; size_t len; if (*(end-1) != 0 || *p == end || (len = strlen(ret)) == 0) return NULL; *p += len + 1; return ret; } static void sanitise(char *buf) { unsigned char *q, *r; for (q = r = (unsigned char *)buf; *r; r++) if (isprint((int)*r)) *(q++) = *r; *q = 0; } #define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */ static ssize_t tftp_err(int err, char *packet, char *message, char *file) { struct errmess { unsigned short op, err; char message[]; } *mess = (struct errmess *)packet; ssize_t len, ret = 4; char *errstr = strerror(errno); memset(packet, 0, daemon->packet_buff_sz); sanitise(file); mess->op = htons(OP_ERR); mess->err = htons(err); len = snprintf(mess->message, MAXMESSAGE, message, file, errstr); ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */ my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message); return ret; }
void check_tftp_listeners(time_t now) { struct tftp_transfer *transfer, *tmp, **up; ssize_t len; struct ack { unsigned short op, block; } *mess = (struct ack *)daemon->packet; /* Check for activity on any existing transfers */ for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp) { tmp = transfer->next; prettyprint_addr(&transfer->peer, daemon->addrbuff); if (poll_check(transfer->sockfd, POLLIN)) { /* we overwrote the buffer... */ daemon->srv_save = NULL; if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack)) { if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block) { /* Got ack, ensure we take the (re)transmit path */ transfer->timeout = now; transfer->backoff = 0; if (transfer->block++ != 0) transfer->offset += transfer->blocksize - transfer->expansion; } else if (ntohs(mess->op) == OP_ERR) { char *p = daemon->packet + sizeof(struct ack); char *end = daemon->packet + len; char *err = next(&p, end); /* Sanitise error message */ if (!err) err = ""; else sanitise(err); my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"), (int)ntohs(mess->block), err, daemon->addrbuff); /* Got err, ensure we take abort */ transfer->timeout = now; transfer->backoff = 100; } } } if (difftime(now, transfer->timeout) >= 0.0) { int endcon = 0; /* timeout, retransmit */ transfer->timeout += 1 + (1<<transfer->backoff); /* we overwrote the buffer... */ daemon->srv_save = NULL; if ((len = get_block(daemon->packet, transfer)) == -1) { len = tftp_err_oops(daemon->packet, transfer->file->filename); endcon = 1; } /* don't complain about timeout when we're awaiting the last ACK, some clients never send it */ else if (++transfer->backoff > 7 && len != 0) { endcon = 1; len = 0; } if (len != 0) while(sendto(transfer->sockfd, daemon->packet, len, 0, (struct sockaddr *)&transfer->peer, sa_len(&transfer->peer)) == -1 && errno == EINTR); if (endcon || len == 0) { strcpy(daemon->namebuff, transfer->file->filename); sanitise(daemon->namebuff); my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff); /* unlink */ *up = tmp; if (endcon) free_transfer(transfer); else { /* put on queue to be sent to script and deleted */ transfer->next = daemon->tftp_done_trans; daemon->tftp_done_trans = transfer; } continue; } } up = &transfer->next; } }
// returns bool inserted bool db_primitive_insert_game( bool &signal_error, const char *white, const char *black, const char *event, const char *site, const char *round, const char *result, const char *date, const char *white_elo, const char *black_elo, const char *eco, int nbr_moves, thc::Move *moves, uint64_t *hashes ) { signal_error = false; // use this mechanism because returning false doesn't necessarily mean error char *errmsg; char insert_buf[2000]; char blob_txt_buf[4000]; // about 500 moves each char blob_buf[2000]; char white_buf[200]; char black_buf[200]; char event_buf[200]; char site_buf[200]; char round_buf[200]; char eco_buf[200]; if( nbr_moves < 3 ) // skip 'games' with zero, one or two moves return false; // not inserted, not error if( white_elo && black_elo ) { int elo_w = atoi(white_elo); int elo_b = atoi(black_elo); if( 0<elo_w && elo_w<2000 && 0<elo_b && elo_b<2000 ) // if any elo information, need at least one good player return false; // not inserted, not error } bool alphaWhite = sanitise( white, white_buf, sizeof(white_buf) ); bool alphaBlack = sanitise( black, black_buf, sizeof(black_buf) ); if( !alphaWhite || !alphaBlack ) // skip games with no names return false; // not inserted, not error sanitise( event, event_buf, sizeof(event_buf) ); sanitise( site, site_buf, sizeof(site_buf) ); sanitise( round, round_buf, sizeof(round_buf) ); sanitise( eco, eco_buf, sizeof(eco_buf) ); CompressMoves press; uint64_t hash = press.cr.Hash64Calculate(); uint64_t counter=0, game_hash=hash; char *put_txt = blob_txt_buf; char *put = blob_buf; for( int i=0; i<nbr_moves && put_txt<blob_txt_buf+sizeof(blob_txt_buf)-10; i++ ) { thc::Move mv = moves[i]; char c = press.CompressMove(mv); *put++ = c; char hi = (c>>4)&0x0f; *put_txt++ = (hi>=10 ? hi-10+'A' : hi+'0'); char lo = c&0x0f; *put_txt++ = (lo>=10 ? lo-10+'A' : lo+'0'); hash = press.cr.Hash64Update( hash, mv ); game_hash = game_hash ^ hash ^ counter; counter++; } *put_txt = '\0'; *put = '\0'; // Try to insert the game sprintf( insert_buf, "INSERT INTO games VALUES(%d,%lld,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',X'%s')", game_id, game_hash, white_buf, black_buf, event_buf, site_buf, round_buf, result, date, white_elo, black_elo, eco_buf, blob_txt_buf ); int retval = sqlite3_exec( handle, insert_buf,0,0,&errmsg); // This is one spot where a database failure is (kind of) expected - the game_hash has "unique" property if( retval && errmsg ) { char buf[200]; strncpy( buf, errmsg, sizeof(buf)-1 ); buf[ sizeof(buf)-1 ] = '\0'; char *p = buf; while( *p ) { if( isalpha(*p) && isupper(*p) ) *p = tolower(*p); p++; } // If it wasn't a "unique" issue, we bail out if( !strstr(buf,"unique") ) { char buf2[1000]; sprintf( buf2, "Database error: db_primitive_insert_game() 1 %s (%s)\n", errmsg, insert_buf ); error_msg = buf2; signal_error = true; return false; // not inserted, error } //cprintf("Non unique game hash %s (%s)\n", errmsg, insert_buf ); // Otherwise see if the game is a duplicate of existing game (if it's not, then it will be the same // game played on a different occasion) bool is_duplicate = db_primitive_check_for_duplicate( signal_error, game_hash, white_buf, black_buf, result, blob_buf ); if( signal_error ) return false; // not inserted, error // A duplicate game is simply discarded if( is_duplicate ) { //cprintf( "*** DUPLICATE GAME DISCARDED\n" ); // ZOMBIE bug fix - return here, don't add bogus moves and increment game count //db_temporary_hack( white, black, event, site, round, result, // date, white_elo, black_elo, eco, // nbr_moves, moves ); return false; // not inserted, not error } // If it's the same game played by different players, save it with game_hash NULL, which is doesn't have to // be unique fortunately else { //cprintf( "*** DUPLICATE GAME: %s-%s %s %s %s\n", white_buf, black_buf, event_buf, site_buf, result, date ); sprintf( insert_buf, "INSERT INTO games VALUES(%d,NULL,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',X'%s')", game_id, white_buf, black_buf, event_buf, site_buf, round_buf, result, date, white_elo, black_elo, eco_buf, blob_txt_buf ); int retval = sqlite3_exec( handle, insert_buf,0,0,&errmsg); if( retval && errmsg ) { char buf2[1000]; sprintf( buf2, "Database error: db_primitive_insert_game() 2 %s (%s)", errmsg, insert_buf ); signal_error = true; return false; // not inserted, error } else if( retval ) { char buf2[1000]; sprintf( buf2, "Database error: db_primitive_insert_game() 2 (%s)", insert_buf ); signal_error = true; return false; // not inserted, error } sprintf( insert_buf, "INSERT INTO games_duplicates VALUES(%d,%lld,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',X'%s')", game_id, game_hash, white_buf, black_buf, event_buf, site_buf, round_buf, result, date, white_elo, black_elo, eco_buf, blob_txt_buf ); retval = sqlite3_exec( handle, insert_buf,0,0,&errmsg); if( retval && errmsg ) { char buf2[1000]; sprintf( buf2, "Database error: db_primitive_insert_game() 3 %s (%s)", errmsg, insert_buf ); signal_error = true; return false; // not inserted, error } else if( retval ) { char buf2[1000]; sprintf( buf2, "Database error: db_primitive_insert_game() 3 (%s)", insert_buf ); signal_error = true; return false; // not inserted, error } } } // Save the position hashes for( int i=0; i<nbr_moves; i++ ) { uint64_t hash64 = *hashes++; int hash32 = (int)(hash64); int table_nbr = ((int)(hash64>>32))&(NBR_BUCKETS-1); std::vector<std::pair<int,int>> *bucket = &buckets[table_nbr]; std::pair<int,int> duo(hash32,game_id); bucket->push_back(duo); int count = bucket->size(); if( count >= PURGE_QUOTA ) { bool ok = purge_bucket(table_nbr); if( !ok ) { signal_error = true; return false; // not inserted, error } } } game_id++; return true; // inserted, no error }