void send_confstartendupdate(connection_t *c, int start) { char rawconf[MAX_STRING_SIZE]; char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE]; size_t slen, dlen, rlen; char *fname; bool choice = false; /* test if we're are authorized to broadcast the data */ if(!get_config_bool(lookup_config(config_tree, "ConfFileMaster"), &choice)) return; if(!choice) return; if(c->node && c->node->sentupdates) return; if(get_config_string(lookup_config(config_tree, "ConfFileTemplate"), &fname)) free(fname); else return; /* Start update session */ dlen = RSA_size(myself->connection->rsa_key); if (dlen > sizeof(rawdgst)/2) { logger(LOG_ERR, "Could not %s config update session due to digest overflow", start ? "start" : "end"); return; } snprintf(rawconf, sizeof(rawconf), "%s %s 0 %zd", myself->name, start ? "START" : "END", dlen); rlen = strlen(rawconf); if (!EVP_sign(myself->connection->rsa_key, rawconf, rlen, rawdgst, &dlen)) { logger(LOG_ERR, "Could not %s config update session due to signing error (probably OOM)", start ? "start" : "end"); return; } if (base64_enclen(dlen) >= MAX_STRING_SIZE) { logger(LOG_ERR, "Could not %s config update session, base64 digest overflow", start ? "start" : "end"); return; } base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1); send_request(c, "%d %s %s", CONFUPDATE, rawconf, b64dgst); }
void send_hostsstartendupdate(connection_t *c, int start) { char rawhost[MAX_STRING_SIZE]; char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE]; size_t slen, dlen, rlen; bool choice = false; /* test if we're are authorized to broadcast the data */ if(!get_config_bool(lookup_config(config_tree, "HostsFilesMaster"), &choice)) return; if(!choice) return; /* bootstrapped node? If we're already sent him updates, do not do that again */ if(c->node && c->node->sentupdates) return; /* Start update session */ dlen = RSA_size(myself->connection->rsa_key); if (dlen > sizeof(rawdgst)/2) { logger(LOG_ERR, "Could not %s hosts update session due to digest overflow", start ? "start" : "end"); return; } snprintf(rawhost, sizeof(rawhost), "%s %s %s 0 %zd", myself->name, myself->name, start ? "START" : "END", dlen); rlen = strlen(rawhost); if (!EVP_sign(myself->connection->rsa_key, rawhost, rlen, rawdgst, &dlen)) { logger(LOG_ERR, "Could not %s hosts update session due to signing error (probably OOM)", start ? "start" : "end"); return; } if (base64_enclen(dlen) >= MAX_STRING_SIZE) { logger(LOG_ERR, "Could not %s hosts update session, base64 digest overflow", start ? "start" : "end"); return; } base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1); send_request(c, "%d %s %s", HOSTUPDATE, rawhost, b64dgst); }
STATIC int parameter_size(negotiation_parameter_t *par) { int i, size; char buf[24]; /* max. 2 10-digit numbers + sep. */ if (par->key > MAX_KEY) { return strlen(par->val.sval) + 15; } /* count '=' and terminal zero */ size = strlen(entries[par->key].name) + 2; for (i = 0; i < par->list_num; i++) { switch (entries[par->key].val) { case T_NUM: size += snprintf(buf, sizeof(buf), "%d", par->val.nval[i]); break; case T_BIGNUM: /* list_num holds value size */ #ifdef ISCSI_HEXBIGNUMS size += 2 + 2*par->list_num; #else size += base64_enclen(par->list_num); #endif i = par->list_num; break; case T_STRING: case T_SENDT: size += strlen(par->val.sval); break; case T_YESNO: size += (par->val.nval[i]) ? 3 : 2; break; case T_AUTH: size += (par->val.nval[i] == ISCSI_AUTH_SRP) ? 3 : 4; break; case T_DIGEST: size += (par->val.nval[i]) ? 6 : 4; break; case T_RANGE: assert((i + 1) < par->list_num); size += snprintf(buf, sizeof(buf), "%d~%d", par->val.nval[i], par->val.nval[i + 1]); i++; break; case T_SESS: size += (par->val.nval[i]) ? 6 : 9; break; default: /* We should't be here... */ DEBOUT(("Invalid type %d in parameter_size!\n", entries[par->key].val)); break; } if ((i + 1) < par->list_num) { size++; } } return size; }
/* Pretty same as hosts, but only for one file */ void send_confupdate(connection_t *c) { char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE]; char rawconf[MAX_STRING_SIZE], b64conf[MAX_STRING_SIZE]; char *fname, *tname; FILE *fp; size_t slen, dlen, rlen; bool choice = false; if(!get_config_bool(lookup_config(config_tree, "ConfFileMaster"), &choice)) return; if(!choice) return; if(c->node && c->node->sentupdates) return; dlen = RSA_size(myself->connection->rsa_key); if (dlen > sizeof(rawdgst)/2) { logger(LOG_ERR, "Could not send config update due to digest overflow"); return; } if(get_config_string(lookup_config(config_tree, "ConfFileTemplate"), &fname) && ((strcmp(fname, "tinc.conf") != 0) && (strcmp(fname, "rsa_key.priv") != 0))) { dlen = RSA_size(myself->connection->rsa_key); if (dlen > sizeof(rawdgst)/2) { logger(LOG_ERR,"Could not start config update session due to digest overflow"); free(fname); return; } xasprintf(&tname, "%s/%s", confbase, fname); fp = fopen(tname, "r"); if (!fp) { logger(LOG_ERR, "Could not open ConfFileTemplate %s and send it!", tname); free(tname); free(fname); return; } slen = fread(rawconf, 1, sizeof(rawconf), fp); fclose(fp); if (base64_enclen(slen) >= MAX_STRING_SIZE) { logger(LOG_ERR, "Config data %s is too long to base64 encode", tname); free(tname); free(fname); return; } base64_encode(rawconf, slen, b64conf, sizeof(b64conf)-1); snprintf(rawconf, sizeof(rawconf), "%s %s %zd %zd", myself->name, b64conf, slen, dlen); free(tname); free(fname); rlen = strlen(rawconf); if (!EVP_sign(myself->connection->rsa_key, rawconf, rlen, rawdgst, &dlen)) { logger(LOG_ERR, "Could not sign config update due to signing error (probably OOM)"); return; } if (base64_enclen(dlen) >= MAX_STRING_SIZE) { logger(LOG_ERR, "Could not sign config update, base64 digest overflow"); return; } base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1); send_request(c, "%d %s %s", CONFUPDATE, rawconf, b64dgst); } }
void send_hostsupdates(connection_t *c) { /* FIXME: Too memory hungry */ char rawfile[MAX_STRING_SIZE]; char rawhost[MAX_STRING_SIZE], b64host[MAX_STRING_SIZE]; char rawdgst[MAX_STRING_SIZE], b64dgst[MAX_STRING_SIZE]; char *fname, *dname; struct stat s; DIR *dir; FILE *fp; struct dirent *ent; size_t slen, dlen, rlen; bool choice = false; /* test if we're are authorized to broadcast the data */ if(!get_config_bool(lookup_config(config_tree, "HostsFilesMaster"), &choice)) return; if(!choice) return; if(c->node && c->node->sentupdates) return; dlen = RSA_size(myself->connection->rsa_key); if (dlen > sizeof(rawdgst)/2) { logger(LOG_ERR, "Could not send hosts updates due to digest overflow"); return; } /* broadcast complete host data as is (as on disk) we own */ xasprintf(&dname, "%s/hosts", confbase); dir = opendir(dname); free(dname); if(!dir) return; /* I hope receiving node can accept and write updates quickly enough. */ while((ent = readdir(dir))) { if(!check_id(ent->d_name)) continue; xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name); fp = fopen(fname, "r"); if (!fp) { logger(LOG_ERR, "Could not open host file %s: %s", fname, strerror(errno)); free(fname); continue; } slen = fread(rawfile, 1, sizeof(rawfile), fp); fclose(fp); if (base64_enclen(slen) >= MAX_STRING_SIZE) { logger(LOG_WARNING, "Host file %s too long to send", fname); free(fname); continue; } base64_encode(rawfile, slen, b64host, sizeof(b64host)-1); snprintf(rawhost, sizeof(rawhost), "%s %s %s %zd %zd", myself->name, ent->d_name, b64host, slen, dlen); rlen = strlen(rawhost); if (!EVP_sign(myself->connection->rsa_key, rawhost, rlen, rawdgst, &dlen)) { logger(LOG_ERR, "Could not sign update for %s due to signing error (probably OOM)", ent->d_name); continue; } if (base64_enclen(dlen) >= MAX_STRING_SIZE) { logger(LOG_WARNING, "Digest for host file %s too long to send", fname); free(fname); continue; } base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1); send_request(c, "%d %s %s", HOSTUPDATE, rawhost, b64dgst); free(fname); } closedir(dir); /* Again, but for "dead" hosts */ xasprintf(&dname, "%s/hosts", confbase); dir = opendir(dname); free(dname); if(!dir) return; /* send a list of dead hosts */ while((ent = readdir(dir))) { if(!check_id(ent->d_name)) continue; if(getconf_bool_node_offline(ent->d_name, "DeadHost")) { snprintf(rawhost, sizeof(rawhost), "%s %s DEAD 0 %zd", myself->name, ent->d_name, dlen); rlen = strlen(rawhost); if (!EVP_sign(myself->connection->rsa_key, rawhost, rlen, rawdgst, &dlen)) { logger(LOG_ERR, "Could not sign dead for %s due to signing error (probably OOM)", ent->d_name); continue; } if (base64_enclen(dlen) >= MAX_STRING_SIZE) { logger(LOG_ERR, "Digest for dead host file %s too long to send", ent->d_name); continue; } base64_encode(rawdgst, dlen, b64dgst, sizeof(b64dgst)-1); send_request(c, "%d %s %s", HOSTUPDATE, rawhost, b64dgst); } } closedir(dir); }