Protocol::Protocol (int type, string logfile)
{
	log = logfile;
        LOG(log, "** Protocol Constructor **\n");
        
        if (type == CLIENT) {
                int fd = open("key_client", O_RDONLY);
                read(fd, (void *) &client_id, sizeof(uint32_t));
                read(fd, (void *) shared_key, EVP_MAX_KEY_LENGTH);
                close(fd);
                generate_nonce((char *) &client_nonce);

                // log
                LOG(log, "\t\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\t\tShared key: " +
                    stringbyte(shared_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "\t\tClient nonce: " + utos(client_nonce) + "\n");
        }
        server_id = ID_SERVER;
        md_ctx = create_md_context();
        md_len = EVP_MD_size(md_ctx->digest);

        // log
        LOG(log, "\t\tServer ID: " + utos(server_id) + "\n");
        LOG(log, "** End constructor **\n\n");
}
Ejemplo n.º 2
0
int16_t log_uint(uint32_t n)
{
	if (state == UNINITIALIZED)
		return -ENOREADY;

	log_string(utos(n));

	return 0;
}
Ejemplo n.º 3
0
void			Showcase::display(reports const rep, reports const oldrep)
{
  std::stringstream	sstr;
  int			i, j, x, y;
  int			ready[NB_PIZZA];
  constitreports       	it;

  for (i = 0; i < NB_PIZZA; ready[i++] = 0);
  _win.Clear(sf::Color(0, 0, 0));
  if (_note.length() > 32)
    _text.SetText(_note.substr((_note.length() - 32), 32));
  else
    _text.SetText(_note);
  _win.Draw(_spritemenu);
  _win.Draw(_text);
  for (it = rep.begin(), i = 0, x = 15, y = 385; it != rep.end(); ++it, ++i, y += 30)
    {
      for (j = 0; j < NB_PIZZA; ++j)
	ready[j] += (*it).ready[j];
      _ready.SetPosition(x, y);
      _ready.SetText("Cuisine " + utos(i + 1) + " : "
		     + utos((*it).inPrep) + " en preparation et "
		     + utos((*it).waiting) + " en attente.");
      _win.Draw(_ready);
      
    }
  for (it = oldrep.begin(); it != oldrep.end(); ++it)
    for (j = 0; j < NB_PIZZA; ++j)
      ready[j] += (*it).ready[j];
  for (i = 0, x = 305, y = 318; i < NB_PIZZA; ++i)
    {
      _ready.SetPosition(x + i * 125, y);
      _ready.SetText(utos(ready[i]));
      _win.Draw(_ready);
    }
  _win.Display();
}
Ejemplo n.º 4
0
map<string, CanVariable> CanIdTranslator::translateData(vector<XmlNode> variableNodes, string dataHex)
{
	map<string, CanVariable> variables;
	string dataBin = hex2bin(dataHex);
	//dataBin = rpad(dataBin, 64, '0');

	for (int c = 0; c < variableNodes.size(); c++)
	{
		map<string, string> attributes = variableNodes[c].getAttributes();

		int bitStart = stoi(attributes["start_bit"]);
		int bitLength = stoi(attributes["bit_length"]);
		string bits;

		try
		{
			bits = dataBin.substr(bitStart, bitLength);
		}
		catch (std::out_of_range& e)
		{
			return variables;
		}

		CanVariable variable;

		variable.setName(attributes["name"]);
		variable.setType(attributes["type"]);
		variable.setUnit(attributes["unit"]);
		variable.setStartBit(bitStart);
		variable.setBitLength(bitLength);

		if (attributes["type"] == "uint")
		{
			variable.setValue(utos(bin2uint(bits)));
		}
		else if (attributes["type"] == "float")
		{
			variable.setValue(ftos(bin2float(bits)));
		}
		else if (attributes["type"] == "enum")
		{
			vector<XmlNode> values = variableNodes[c].getChildren();

			string value = utos(bin2uint(bits));

			for (int k = 0; k < values.size(); k++)
			{
				map<string, string> valueAttributes = values[k].getAttributes();
				variable.addEnumValue(valueAttributes["id"], valueAttributes["name"]);

				if (valueAttributes["id"] == value)
				{
					variable.setValue(valueAttributes["name"]);
				}
			}
		}
		else if (attributes["type"] == "ascii")
		{
			string str;

			for (int k = 0; k < bits.length(); k += 8)
			{
				try
				{
					str += (char)bin2uint(bits.substr(k, 8));
				}
				catch (std::out_of_range& e)
				{
					cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
					cout << "DEBUG: B bits=" << bits << " :: k=" << k << endl;
					continue;
				}
			}

			variable.setValue(str);
		}
		else if (attributes["type"] == "hexstring")
		{
			string str;

			for (int k = 0; k < bits.length(); k += 4)
			{
				try
				{
					str += bin2hex(bits.substr(k, 4));
				}
				catch (std::out_of_range& e)
				{
					cout << "DEBUG: TranslateData exception: " << e.what() << "\n";
					cout << "DEBUG: C bits=" << bits << " :: k=" << k << endl;
					continue;
				}
			}

			variable.setValue(str);
		}

		variables[attributes["name"]] = variable;
	}

	return variables;
}
Ejemplo n.º 5
0
static int console_ansi_cursor_control( Console* cons, uint op, uint op1, uint op2, uint op3 )
{
	char cmdbuf[ 32 ] = {0};
	int cmdsize = 0;
	int status = 0;

	CURSOR_CONTROL_ASSIGN_CMD( 27 );

	switch( op ){
		/* ESC group */
	case CURSOR_CONTROL_SAVE:
		CURSOR_CONTROL_ASSIGN_CMD( '7' );
		break;
	case CURSOR_CONTROL_RESTORE:
		CURSOR_CONTROL_ASSIGN_CMD( '8' );
		break;
		
		/* CSI group */
	case CURSOR_CONTROL_SET_POS:
	case CURSOR_CONTROL_CLS:
	case CURSOR_CONTROL_REMOVE_LEFT:
		CURSOR_CONTROL_ASSIGN_CMD( '[' );
		break;
	default:
		return ERR_INVALID_ARGUMENT;
	}

	/* CSI extra parameters */
	switch( op ){
	case CURSOR_CONTROL_CLS:
		CURSOR_CONTROL_ASSIGN_CMD( '2' );
		CURSOR_CONTROL_ASSIGN_CMD( 'J' );
		break;
	case CURSOR_CONTROL_REMOVE_LEFT:
		cmdsize += utos( op1, cmdbuf + cmdsize );
		CURSOR_CONTROL_ASSIGN_CMD( 'X' );
		break;
	case CURSOR_CONTROL_BACK:
		cmdsize += utos( op1, cmdbuf + cmdsize );
		CURSOR_CONTROL_ASSIGN_CMD( 'D' );
		break;
	case CURSOR_CONTROL_INSERT:
		cmdsize += utos( op1, cmdbuf + cmdsize );
		CURSOR_CONTROL_ASSIGN_CMD( '@' );
		break;
		/* CLS 2 parameters */
	case CURSOR_CONTROL_SET_POS:
		cmdsize += utos( op1, cmdbuf + cmdsize );
		CURSOR_CONTROL_ASSIGN_CMD( ';' );
		cmdsize += utos( op2, cmdbuf + cmdsize );
		CURSOR_CONTROL_ASSIGN_CMD( 'H' );
		break;
	}

	/* Send command to terminal */
	status = console_write_guarantee( cons, ( uchar* )cmdbuf, cmdsize );
	ASSERT( status == ERR_NONE );

	while( ! console_ready_write( cons ) );
	
	return ERR_NONE;	
}
int Protocol::receive_data (int sd, char *&buf, int *len)
{
        // log
        LOG(log, "** Receiving Data **\n");

        int n = sizeof(uint32_t);
        int p = 0;
        uint32_t length;

        // Receive:
        // M = IV, {C_ID, S_ID, buf, h(C_ID, S_ID, buf, IV)}

        // receive length
        int ret, r = 0;
        do {
                ret = read(sd, (void *) (&length + r), n - r);
                if (ret == -1)
                        return ret;
                r += ret;
        } while (r != n);
        if (length <= (EVP_MAX_IV_LENGTH + 2 * n + md_len))
                return -1;

        // buffers
        int td_len;
        int p_len;
        int c_len = length - EVP_MAX_IV_LENGTH;
        char *todigest;
        char *md;
        char *r_md = new char[md_len];
        char *plaintxt;
        char *ciphertxt = new char[c_len];
        char *buffer = new char[length];

        // read message
        r = 0;
        do {
                ret = read(sd, (void *) &buffer[r], length - r);
                if (ret == -1)
                        return ret;
                r += ret;
        } while (r != length);

        // iv
        bcopy((void *) &buffer[p], (void *) iv, EVP_MAX_IV_LENGTH);
        p += EVP_MAX_IV_LENGTH;

        // ciphertext:  {C_ID, S_ID, buf, h(C_ID, S_ID, buf, IV)}
        bcopy((void *) &buffer[p], (void *) ciphertxt, c_len);

        // plaintext: C_ID, S_ID, buf, h(C_ID, S_ID, buf, IV)
        dec_ctx = create_context(session_key, iv, DEC);
        plaintxt = decrypt(dec_ctx, ciphertxt, c_len, &p_len);
        EVP_CIPHER_CTX_cleanup(dec_ctx);

        // check
        uint32_t tmp;
        p = 0;
        bcopy((void *) &plaintxt[p], (void *) &tmp, n);
        if (tmp != client_id) {
                printf("esco qui\n");
                return -1;
        }
        p += n;
        bcopy((void *) &plaintxt[p], (void *) &tmp, n);
        if (tmp != server_id)
                return -1;
        p += n;

        // data
        *len = p_len - (2 * n + md_len);
        buf = new char[*len];
        bcopy((void *) &plaintxt[p], (void *) buf, *len);
        p += *len;

        // received hash
        bcopy((void *) &plaintxt[p], (void *) r_md, md_len);

        // todigest: C_ID, S_ID, buf, IV
        p = 0;
        td_len = 2 * n + *len + EVP_MAX_IV_LENGTH;
        todigest = new char[td_len];
        bcopy((void *) &client_id, (void *) &todigest[p], n);
        p += n;
        bcopy((void *) &server_id, (void *) &todigest[p], n);
        p += n;
        bcopy((void *) buf, (void *) &todigest[p], *len);
        p += *len;
        bcopy((void *) iv, (void *) &todigest[p], EVP_MAX_IV_LENGTH);

        // hash
        md = digest(md_ctx, todigest, td_len);

        // check hash
        for (int i = 0; i < md_len; i++) {
                if (md[i] != r_md[i])
                        return -1;
        }

        // log
        LOG(log, "\tLength: " + utos(length) + "\n");
        LOG(log, "\tIV: " + stringbyte(iv, EVP_MAX_IV_LENGTH) + "\n");
        LOG(log, "\tClient ID: " + utos(client_id) + "\n");
        LOG(log, "\tServer ID: " + utos(server_id) + "\n");
        LOG(log, "\tMD: " + stringbyte(md, md_len) + "\n");
        LOG(log, "\tCipher Text: " + stringbyte(ciphertxt, c_len) + "\n");
        LOG(log, "\tData: " + stringbyte(buf, *len) + "\n");
        LOG(log, "\tSession Key (decrypt): " + 
            stringbyte(session_key, EVP_MAX_KEY_LENGTH) + "\n");
        LOG(log, "** Data Received **\n\n");

        // garbage collection
        delete[] todigest;
        delete[] md;
        delete[] r_md;
        delete[] plaintxt;
        delete[] ciphertxt;
        delete[] buffer;

        return 0;
}
int Protocol::send_data (int sd, char *buf, int len)
{
        // log
        LOG(log, "** Sending Data **\n");

        int n = sizeof(uint32_t);
        int p = 0;
        uint32_t length;

        // buffers
        int td_len = 2 * n + len + EVP_MAX_IV_LENGTH;
        int p_len = td_len + md_len - EVP_MAX_IV_LENGTH;
        int c_len;
        int b_len;
        char *todigest = new char[td_len];
        char *md;
        char *plaintxt = new char[p_len];
        char *ciphertxt;
        char *buffer;

        // to digest: C_ID, S_ID, buf, IV
        bcopy((void *) &client_id, (void *) &todigest[p], n);
        p += n;
        bcopy((void *) &server_id, (void *) &todigest[p], n);
        p += n;
        bcopy((void *) buf, (void *) &todigest[p], len);
        p += len;
        select_random_iv(iv, EVP_MAX_IV_LENGTH);
        bcopy((void *) iv, (void *) &todigest[p], EVP_MAX_IV_LENGTH);

        // hash
        md = digest(md_ctx, todigest, td_len);

        // plaintext: C_ID, S_ID, buf, h(C_ID, S_ID, buf, IV)
        p = 0;
        bcopy((void *) todigest, (void *) &plaintxt[p], p_len - md_len);
        p += p_len - md_len;
        bcopy((void *) md, (void *) &plaintxt[p], md_len);

        // ciphertext: {C_ID, S_ID, buf, h(C_ID, S_ID, buf, IV)}
        enc_ctx = create_context(session_key, iv, ENC);
        ciphertxt = encrypt(enc_ctx, plaintxt, p_len, &c_len);
        EVP_CIPHER_CTX_cleanup(enc_ctx);

        // Message length
        length = c_len + EVP_MAX_IV_LENGTH;

        // Send:
        // M = IV, {C_ID, S_ID, buf, h(C_ID, S_ID, buf, IV)}
        p = 0;
        b_len = length + n;
        buffer = new char[b_len];
        bcopy((void *) &length, (void *) &buffer[p], n);
        p += n;
        bcopy((void *) iv, (void *) &buffer[p], EVP_MAX_IV_LENGTH);
        p += EVP_MAX_IV_LENGTH;
        bcopy((void *) ciphertxt, (void *) &buffer[p], c_len);

        // send
        p = 0;
        int ret;
        do {
                ret = write (sd, (void *) &buffer[p], b_len - p);
                if (ret == -1)
                        return ret;
                p += ret;
        } while (p != b_len);

        // log
        LOG(log, "\tLength: " + utos(length) + "\n");
        LOG(log, "\tIV: " + stringbyte(iv, EVP_MAX_IV_LENGTH) + "\n");
        LOG(log, "\tClient ID: " + utos(client_id) + "\n");
        LOG(log, "\tServer ID: " + utos(server_id) + "\n");
        LOG(log, "\tMD: " + stringbyte(md, md_len) + "\n");
        LOG(log, "\tCipher Text: " + stringbyte(ciphertxt, c_len) + "\n");
        LOG(log, "\tData: " + stringbyte(buf, len) + "\n");
        LOG(log, "\tSession Key (encrypt): " + 
            stringbyte(session_key, EVP_MAX_KEY_LENGTH) + "\n");
        LOG(log, "** Data Sent **\n\n");

        // garbage collection
        delete[] todigest;
        delete[] md;
        delete[] plaintxt;
        delete[] ciphertxt;
        delete[] buffer;

        return 0;
}
int Protocol::send_message (int sd, int type)
{
        uint32_t length;
        int len;
        int ret;
        int p = 0;

        if (type == M1) {
                // log
                LOG(log, "** Sending Message M1 **\n");

                // Send to server:
                // M1 = C_ID, S_ID, Na
                len = sizeof(uint32_t);
                length = 3 * len;
                int b_len = 4 * len;

                // message buffer
                char *buffer = new char[b_len];

                // length
                bcopy ((void *) &length, (void *) &buffer[p], len);
                p += len;

                // client_id
                bcopy ((void *) &client_id, (void *) &buffer[p], len);
                p += len;

                // server id
                bcopy ((void *) &server_id, (void *) &buffer[p], len);
                p += len;

                // client nonce
                bcopy ((void *) &client_nonce, (void *) &buffer[p], len);

                // send
                p = 0;
                do {
                        ret = write (sd, (void *) &buffer[p], b_len - p);
                        if (ret == -1)
                                return ret;
                        p += ret;
                } while (p != b_len);

                // log
                LOG(log, "\tLength: " + utos(length) + "\n");
                LOG(log, "\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\tServer ID: " + utos(server_id) + "\n");
                LOG(log, "\tClient Nonce: " + utos(client_nonce) + "\n");
                LOG(log, "** Message M1 sent **\n\n");

                // garbage collection
                delete[] buffer;
        }

        if (type == M2) {
                // log
                LOG(log, "** Sending Messagge M2 **\n");

                // buffers
                int td_len = 3 * sizeof(uint32_t) + EVP_MAX_KEY_LENGTH +
                             EVP_MAX_IV_LENGTH;
                int p_len = td_len + md_len - EVP_MAX_IV_LENGTH;
                int c_len;
                int b_len;
                char *todigest = new char[td_len];
                char *md;
                char *plaintxt = new char[p_len];
                char *ciphertxt;
                char *buffer;

                // to digest: S_ID, C_ID, Na, K, IV
                len = sizeof(uint32_t);
                bcopy ((void *) &server_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) &client_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) &client_nonce, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) session_key, (void *) &todigest[p],
                       EVP_MAX_KEY_LENGTH);
                p += EVP_MAX_KEY_LENGTH;
                select_random_iv(iv, EVP_MAX_IV_LENGTH);
                bcopy ((void *) iv, (void *) &todigest[p], EVP_MAX_IV_LENGTH);

                // hash
                md = digest(md_ctx, todigest, td_len);

                // plaintext: S_ID, C_ID, Na, K, h(S_ID, C_ID, Na, K, IV)
                p = 0;
                bcopy ((void *) todigest, (void *) &plaintxt[p], td_len -
                       EVP_MAX_IV_LENGTH);
                p += td_len - EVP_MAX_IV_LENGTH;
                bcopy ((void *) md, (void *) &plaintxt[p], md_len);

                // ciphertext: {S_ID, C_ID, Na, K, h(S_ID, C_ID, Na, K, IV)}
                enc_ctx = create_context(shared_key, iv, ENC);
                ciphertxt = encrypt(enc_ctx, plaintxt, p_len, &c_len);

                // M2 length
                length = c_len + EVP_MAX_IV_LENGTH;

                // Send to client:
                // M2 = IV, {S_ID, C_ID, Na, K, h(S_ID, C_ID, Na, K, IV)}
                p = 0;
                b_len = length + sizeof(length);
                buffer = new char[b_len];
                bcopy ((void *) &length, (void *) &buffer[p], sizeof(length));
                p += sizeof(length);
                bcopy ((void *) iv, (void *) &buffer[p], EVP_MAX_IV_LENGTH);
                p += EVP_MAX_IV_LENGTH;
                bcopy ((void *) ciphertxt, (void *) &buffer[p], c_len);

                // send
                p = 0;
                do {
                        ret = write (sd, (void *) &buffer[p], b_len - p);
                        if (ret == -1)
                                return ret;
                        p += ret;
                } while (p != b_len);

                // log
                LOG(log, "\tLength: " + utos(length) + "\n");
                LOG(log, "\tIV: " + stringbyte(iv, EVP_MAX_IV_LENGTH) + "\n");
                LOG(log, "\tServer ID: " + utos(server_id) + "\n");
                LOG(log, "\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\tClient Nonce: " + utos(client_nonce) + "\n");
                LOG(log, "\tSession Key: " + 
                    stringbyte(session_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "\tMD: " + stringbyte(md, md_len) + "\n");
                LOG(log, "\tCipher Text: " + stringbyte(ciphertxt, c_len) +
                    "\n");
                LOG(log, "\tShared Key (encrypt): " + 
                    stringbyte(shared_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "** Message M2 sent **\n\n");

                // garbage collection
                delete[] todigest;
                delete[] md;
                delete[] plaintxt;
                delete[] ciphertxt;
                delete[] buffer;
        }

        if (type == M3) {
                // log
                LOG(log, "** Sending Message M3 **\n");

                // buffers
                int td_len = 2 * sizeof(uint32_t) + EVP_MAX_IV_LENGTH;
                int p_len = td_len + md_len - EVP_MAX_IV_LENGTH;
                int c_len;
                int b_len;
                char *todigest = new char[td_len];
                char *md;
                char *plaintxt = new char[p_len];
                char *ciphertxt;
                char *buffer;

                // to digest: C_ID, S_ID, IV
                len = sizeof(uint32_t);
                bcopy ((void *) &client_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) &server_id, (void *) &todigest[p], len);
                p += len;
                select_random_iv(iv, EVP_MAX_IV_LENGTH);
                bcopy ((void *) iv, (void *) &todigest[p], EVP_MAX_IV_LENGTH);

                // hash
                md = digest(md_ctx, todigest, td_len);

                // plaintext: C_ID, S_ID, h(C_ID, S_ID, IV)
                p = 0;
                bcopy ((void *) todigest, (void *) &plaintxt[p], td_len -
                       EVP_MAX_IV_LENGTH);
                p += td_len - EVP_MAX_IV_LENGTH;
                bcopy ((void *) md, (void *) &plaintxt[p], md_len);

                // ciphertext: {C_ID, S_ID, h(C_ID, S_ID, IV)}
                enc_ctx = create_context(session_key, iv, ENC);
                ciphertxt = encrypt(enc_ctx, plaintxt, p_len, &c_len);

                // M3 length
                length = c_len + EVP_MAX_IV_LENGTH;

                // Send to server:
                // M3 = IV, {C_ID, S_ID, h(C_ID, S_ID, IV)}
                p = 0;
                b_len = length + sizeof(length);
                buffer = new char[b_len];
                bcopy ((void *) &length, (void *) &buffer[p], sizeof(length));
                p += sizeof(length);
                bcopy ((void *) iv, (void *) &buffer[p], EVP_MAX_IV_LENGTH);
                p += EVP_MAX_IV_LENGTH;
                bcopy ((void *) ciphertxt, (void *) &buffer[p], c_len);

                // send
                p = 0;
                do {
                        ret = write (sd, (void *) &buffer[p], b_len - p);
                        if (ret == -1)
                                return ret;
                        p += ret;
                } while (p != b_len);

                // log
                LOG(log, "\tLength: " + utos(length) + "\n");
                LOG(log, "\tIV: " + stringbyte(iv, EVP_MAX_IV_LENGTH) + "\n");
                LOG(log, "\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\tServer ID: " + utos(server_id) + "\n");
                LOG(log, "\tMD: " + stringbyte(md, md_len) + "\n");
                LOG(log, "\tCipher Text: " + stringbyte(ciphertxt, c_len) +
                    "\n");
                LOG(log, "\tSession Key (encrypt): " + 
                    stringbyte(session_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "** Message M3 sent **\n\n");

                // garbage collection
                delete[] todigest;
                delete[] md;
                delete[] plaintxt;
                delete[] ciphertxt;
                delete[] buffer;
        }
        return 0;
}
int Protocol::receive_message (int sd, int type)
{
        uint32_t length;
        uint32_t tmp;
        int len;
        int ret;
        int p = 0;
        int r;

        if (type == M1) {
                // log
                LOG(log, "** Receiving Message M1 **\n");

                // Receive from client:
                // M1 = C_ID, S_ID, Na

                // receive length
                len = sizeof(length);
                r = 0;
                do {
                        ret = read(sd, (void *) (&length + r), len - r);
                        if (ret == -1)
                                return ret;
                        r += ret;
                } while (r != len);
                if (length != 3 * len)
                        return -1;

                // buffer
                char *buffer = new char[length];
                r = 0;
                do {
                        ret = read(sd, (void *) &buffer[r], length - r);
                        if (ret == -1)
                                return ret;
                        r += ret;
                } while (r != length);

                // client id
                bcopy((void *) &buffer[p], (void *) &client_id, len);
                if (client_id < 0)
                        return -1;
                p += len;

                // server id
                bcopy((void *) &buffer[p], (void *) &tmp, len);
                if (tmp != server_id)
                        return -1;
                p += len;

                // client nonce
                bcopy((void *) &buffer[p], (void *) &client_nonce, len);

                // get pre-shared key with client
                get_key(shared_key, "key_server", client_id);

                // log
                LOG(log, "\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\tServer ID: " + utos(server_id) + "\n");
                LOG(log, "\tClient Nonce: " + utos(client_nonce) + "\n");
                LOG(log, "\tShared Key: " +
                    stringbyte(shared_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "** Message M1 Received **\n\n");

                // garbage collection
                delete[] buffer;
        }

        if (type == M2) {
                // log
                LOG(log, "** Receiving Message M2 **\n");

                // Receive from Server:
                // M2 = IV, {S_ID, C_ID, Na, K, h(S_ID, C_ID, Na, K, IV)}

                // receive length
                len = sizeof(length);
                r = 0;
                do {
                        ret = read(sd, (void *) (&length + r), len - r);
                        if (ret == -1)
                                return ret;
                        r += ret;
                } while (r != len);
                if (length < (EVP_MAX_IV_LENGTH + EVP_MAX_KEY_LENGTH + 3 * len
                    + md_len))
                        return -1;

                // buffers
                int td_len = 3 * sizeof(uint32_t) + EVP_MAX_KEY_LENGTH +
                              EVP_MAX_IV_LENGTH;
                int p_len;
                int c_len = length - EVP_MAX_IV_LENGTH;
                char *todigest = new char[td_len];
                char *md;
                char *r_md = new char[md_len];
                char *plaintxt;
                char *ciphertxt = new char[c_len];
                char *buffer = new char[length];

                // receive message
                r = 0;
                do {
                        ret = read(sd, (void *) &buffer[r], length - r);
                        if (ret == -1)
                                return ret;
                        r += ret;
                } while (r != length);

                // iv
                bcopy((void *) &buffer[p], (void *) iv, EVP_MAX_IV_LENGTH);
                p += EVP_MAX_IV_LENGTH;

                // ciphertext: {S_ID, C_ID, Na, K, h(S_ID, C_ID, Na, K, IV)}
                bcopy((void *) &buffer[p], (void *) ciphertxt, c_len);

                // plaintext: S_ID, C_ID, Na, K, h(S_ID, C_ID, Na, K, IV)
                dec_ctx = create_context(shared_key, iv, DEC);
                plaintxt = decrypt(dec_ctx, ciphertxt, c_len, &p_len);

                // store & check
                p = 0;
                bcopy((void *) &plaintxt[p], (void *) &tmp, len);
                if (tmp != server_id)
                        return -1;
                p += len;
                bcopy((void *) &plaintxt[p], (void *) &tmp, len);
                if (tmp != client_id)
                        return -1;
                p += len;
                bcopy((void *) &plaintxt[p], (void *) &tmp, len);
                if (tmp != client_nonce)
                        return -1;
                p += len;
                bcopy((void *) &plaintxt[p], (void *) session_key,
                      EVP_MAX_KEY_LENGTH);
                p += EVP_MAX_KEY_LENGTH;

                // received hash
                bcopy((void *) &plaintxt[p], (void *) r_md, md_len);

                // to digest: S_ID, C_ID, Na, K, IV
                p = 0;
                len = sizeof(uint32_t);
                bcopy ((void *) &server_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) &client_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) &client_nonce, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) session_key, (void *) &todigest[p],
                       EVP_MAX_KEY_LENGTH);
                p += EVP_MAX_KEY_LENGTH;
                bcopy ((void *) iv, (void *) &todigest[p], EVP_MAX_IV_LENGTH);

                // hash
                md = digest(md_ctx, todigest, td_len);

                // check digest
                for (int i = 0; i < md_len; i++) {
                        if (md[i] != r_md[i])
                                return -1;
                }

                // log
                LOG(log, "\tLength: " + utos(length) + "\n");
                LOG(log, "\tIV: " + stringbyte(iv, EVP_MAX_IV_LENGTH) + "\n");
                LOG(log, "\tServer ID: " + utos(server_id) + "\n");
                LOG(log, "\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\tClient Nonce: " + utos(client_nonce) + "\n");
                LOG(log, "\tSession Key: " + 
                    stringbyte(session_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "\tMD: " + stringbyte(md, md_len) + "\n");
                LOG(log, "\tCipher Text: " + stringbyte(ciphertxt, c_len) +
                    "\n");
                LOG(log, "\tShared Key (decrypt): " + 
                    stringbyte(shared_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "** Message M2 Received **\n\n");

                // garbage collection
                delete[] buffer;
                delete[] ciphertxt;
                delete[] plaintxt;
                delete[] r_md;
                delete[] todigest;
                delete[] md;
        }

        if (type == M3) {
                // log
                LOG(log, "** Receiving Message M3 **\n");

                // Receive from client:
                // M3 = IV, {C_ID, S_ID, h(C_ID, S_ID, IV)}

                // receive length
                len = sizeof(length);
                r = 0;
                do {
                        ret = read(sd, (void *) (&length + r), len - r);
                        if (ret == -1)
                                return ret;
                        r += ret;
                } while (r != len);
                if (length < (EVP_MAX_IV_LENGTH + 2 * len + md_len))
                        return -1;

                // buffers
                int td_len = 2 * sizeof(uint32_t) + EVP_MAX_IV_LENGTH;
                int p_len;
                int c_len = length - EVP_MAX_IV_LENGTH;
                char *todigest = new char[td_len];
                char *md;
                char *r_md = new char[md_len];
                char *plaintxt;
                char *ciphertxt = new char[c_len];
                char *buffer = new char[length];

                // read message
                r = 0;
                do {
                        ret = read(sd, (void *) &buffer[r], length - r);
                        if (ret == -1)
                                return ret;
                        r += ret;
                } while (r != length);

                // iv
                bcopy((void *) &buffer[p], (void *) iv, EVP_MAX_IV_LENGTH);
                p += EVP_MAX_IV_LENGTH;

                // ciphertext: {C_ID, S_ID, h(C_ID, S_ID, IV)}
                bcopy((void *) &buffer[p], (void *) ciphertxt, c_len);

                // plaintext: C_ID, S_ID, h(C_ID, S_ID, IV)
                dec_ctx = create_context(session_key, iv, DEC);
                plaintxt = decrypt(dec_ctx, ciphertxt, c_len, &p_len);

                // check
                p = 0;
                len = sizeof(uint32_t);
                bcopy((void *) &plaintxt[p], (void *) &tmp, len);
                if (tmp != client_id)
                        return -1;
                p += len;
                bcopy((void *) &plaintxt[p], (void *) &tmp, len);
                if (tmp != server_id)
                        return -1;
                p += len;

                // received hash
                bcopy((void *) &plaintxt[p], (void *) r_md, md_len);

                // to digest: C_ID, S_ID, IV
                p = 0;
                bcopy ((void *) &client_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) &server_id, (void *) &todigest[p], len);
                p += len;
                bcopy ((void *) iv, (void *) &todigest[p], EVP_MAX_IV_LENGTH);

                // hash
                md = digest(md_ctx, todigest, td_len);

                // check digest
                for (int i = 0; i < md_len; i++) {
                        if (md[i] != r_md[i])
                                return -1;
                }

                // log
                LOG(log, "\tLength: " + utos(length) + "\n");
                LOG(log, "\tIV: " + stringbyte(iv, EVP_MAX_IV_LENGTH) + "\n");
                LOG(log, "\tClient ID: " + utos(client_id) + "\n");
                LOG(log, "\tServer ID: " + utos(server_id) + "\n");
                LOG(log, "\tMD: " + stringbyte(md, md_len) + "\n");
                LOG(log, "\tCipher Text: " + stringbyte(ciphertxt, c_len) +
                    "\n");
                LOG(log, "\tSession Key (decrypt): " + 
                    stringbyte(session_key, EVP_MAX_KEY_LENGTH) + "\n");
                LOG(log, "** Message M3 sent **\n\n");

                // garbage collection
                delete[] buffer;
                delete[] ciphertxt;
                delete[] plaintxt;
                delete[] r_md;
                delete[] todigest;
                delete[] md;
        }

        return 0;
}
Ejemplo n.º 10
0
static inline int ui_switch_names( Console* cons )
{
	/* Switch name */
	Iobuf switchNameIobody;
	Iobuf* switchNameIo;
	Region switchNamebody;
	Region* switchName;
	uchar switchNameBuffer[ UI_SWITCH_NAME_SIZE * 2 ];
	uchar* switchNamebuffers[ 2 ];

	int status = 0;
	int i = 1;
	int switchId = 1;
	uchar curname[ UI_SWITCH_NAME_SIZE ] = UI_SWITCH_NAME;
	uint convSize = 0;

	switchNameIo = &switchNameIobody;
	switchName = &switchNamebody;
	switchNamebuffers[ 0 ] = switchNameBuffer;
	switchNamebuffers[ 1 ] = switchNameBuffer + UI_SWITCH_NAME_SIZE;

	while( 1 ){
		status = iobuf_init( switchNameIo, cons );
		ASSERT( status == ERR_NONE );
	
		status = region_setup( switchName, switchFrame,
				       ( ( ( i - 1 ) % UI_SWITCH_NAME_PER_LINE ) * UI_SWITCH_NAME_SIZE ),
				       ( i - 1 ) / UI_SWITCH_NAME_PER_LINE + 2,
				       UI_SWITCH_NAME_SIZE, 1,
				       0, 0,
				       0, switchNameIo, switchNamebuffers );
		ASSERT( status == ERR_NONE );

		status = region_init( switchName );
		ASSERT( status == ERR_NONE );

		if( i > 18 ){
			switchId = 153 + i - 19;
		} else {
			switchId = i;
		}

		convSize = utos( switchId, (char*)(curname + UI_SWITCH_NAME_NUMBER_OFFSET) );

		switch( convSize ){
		case 1:
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 2 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET ];
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET ] = ' ';
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ] = ' ';
			break;
		case 2:
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 2 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ];
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET ];
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET ] = ' ';
		}
		
		curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 3 ] = ' ';
		curname[ UI_SWITCH_NAME_SIZE - 1 ] = '\0';

		status = region_write( switchName, (char*)curname );
		ASSERT( status == ERR_NONE );

		while( ! region_flushed( switchName ) ){
			status = region_flush( switchName );
			ASSERT( status == ERR_NONE );
		}

		i += 1;
		if( i > SWITCHES_COUNT ){
			break;
		}
	}

	return ERR_NONE;
}
Ejemplo n.º 11
0
void msgs_cfg()
{
	static int dflt,msgs_dflt,bar;
	char	str[256],str2[256],done=0;
	char*	p;
	char*	tp;
    char	tmp[128];
	char	tmp_code[32];
	int		j,k,q,s;
	int		i,file,ptridx,n;
	unsigned total_subs;
	long	ported;
	sub_t	tmpsub;
	static grp_t savgrp;
	FILE*	stream;

while(1) {
	for(i=0;i<cfg.total_grps && i<MAX_OPTS;i++)
		sprintf(opt[i],"%-25s",cfg.grp[i]->lname);
	opt[i][0]=0;
	j=WIN_ORG|WIN_ACT|WIN_CHE;
	if(cfg.total_grps)
		j|=WIN_DEL|WIN_DELACT|WIN_GET;
	if(cfg.total_grps<MAX_OPTS)
		j|=WIN_INS|WIN_INSACT|WIN_XTR;
	if(savgrp.sname[0])
		j|=WIN_PUT;
	uifc.helpbuf=
		"`Message Groups:`\n"
		"\n"
		"This is a listing of message groups for your BBS. Message groups are\n"
		"used to logically separate your message `sub-boards` into groups. Every\n"
		"sub-board belongs to a message group. You must have at least one message\n"
		"group and one sub-board configured.\n"
		"\n"
		"One popular use for message groups is to separate local sub-boards and\n"
		"networked sub-boards. One might have a `Local` message group that contains\n"
		"non-networked sub-boards of various topics and also have a `FidoNet`\n"
		"message group that contains sub-boards that are echoed across FidoNet.\n"
		"Some sysops separate sub-boards into more specific areas such as `Main`,\n"
		"`Technical`, or `Adult`. If you have many sub-boards that have a common\n"
		"subject denominator, you may want to have a separate message group for\n"
		"those sub-boards for a more organized message structure.\n"
	;
	i=uifc.list(j,0,0,45,&msgs_dflt,&bar,"Message Groups",opt);
	if(i==-1) {
		j=save_changes(WIN_MID);
		if(j==-1)
		   continue;
		if(!j) {
			write_msgs_cfg(&cfg,backup_level);
            refresh_cfg(&cfg);
        }
		return;
    }
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
		uifc.helpbuf=
			"`Group Long Name:`\n"
			"\n"
			"This is a description of the message group which is displayed when a\n"
			"user of the system uses the `/*` command from the main menu.\n"
		;
		strcpy(str,"Main");
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Group Long Name",str,LEN_GLNAME
			,K_EDIT)<1)
			continue;
		uifc.helpbuf=
			"`Group Short Name:`\n"
			"\n"
			"This is a short description of the message group which is used for the\n"
			"main menu and reading message prompts.\n"
		;
		sprintf(str2,"%.*s",LEN_GSNAME,str);
		if(uifc.input(WIN_MID,0,0,"Group Short Name",str2,LEN_GSNAME,K_EDIT)<1)
			continue;
		if((cfg.grp=(grp_t **)realloc(cfg.grp,sizeof(grp_t *)*(cfg.total_grps+1)))==NULL) {
            errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_grps+1);
			cfg.total_grps=0;
			bail(1);
            continue; 
		}

		if(cfg.total_grps) {	/* was cfg.total_subs (?) */
            for(j=cfg.total_grps;j>i;j--)   /* insert above */
                cfg.grp[j]=cfg.grp[j-1];
            for(j=0;j<cfg.total_subs;j++)   /* move sub group numbers */
                if(cfg.sub[j]->grp>=i)
                    cfg.sub[j]->grp++; 
		}

		if((cfg.grp[i]=(grp_t *)malloc(sizeof(grp_t)))==NULL) {
			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(grp_t));
			continue; 
		}
		memset((grp_t *)cfg.grp[i],0,sizeof(grp_t));
		strcpy(cfg.grp[i]->lname,str);
		strcpy(cfg.grp[i]->sname,str2);
		cfg.total_grps++;
		uifc.changes=1;
		continue; 
	}
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
		uifc.helpbuf=
			"`Delete All Data in Group:`\n"
			"\n"
			"If you wish to delete the messages in all the sub-boards in this group,\n"
			"select `Yes`.\n"
		;
		j=1;
		strcpy(opt[0],"Yes");
		strcpy(opt[1],"No");
		opt[2][0]=0;
		j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Delete All Data in Group",opt);
		if(j==-1)
			continue;
		if(j==0)
			for(j=0;j<cfg.total_subs;j++)
				if(cfg.sub[j]->grp==i) {
					sprintf(str,"%s%s.s*"
						,cfg.grp[cfg.sub[j]->grp]->code_prefix
						,cfg.sub[j]->code_suffix);
					strlwr(str);
					if(!cfg.sub[j]->data_dir[0])
						sprintf(tmp,"%ssubs/",cfg.data_dir);
					else
						strcpy(tmp,cfg.sub[j]->data_dir);
					delfiles(tmp,str);
					clearptrs(j); 
				}
		free(cfg.grp[i]);
		for(j=0;j<cfg.total_subs;) {
			if(cfg.sub[j]->grp==i) {	/* delete subs of this group */
				free(cfg.sub[j]);
				cfg.total_subs--;
				k=j;
				while(k<cfg.total_subs) {	/* move all subs down */
					cfg.sub[k]=cfg.sub[k+1];
					for(q=0;q<cfg.total_qhubs;q++)
						for(s=0;s<cfg.qhub[q]->subs;s++)
							if(cfg.qhub[q]->sub[s]==k)
								cfg.qhub[q]->sub[s]--;
					k++; 
				} 
			}
			else j++; 
		}
		for(j=0;j<cfg.total_subs;j++)	/* move sub group numbers down */
			if(cfg.sub[j]->grp>i)
				cfg.sub[j]->grp--;
		cfg.total_grps--;
		while(i<cfg.total_grps) {
			cfg.grp[i]=cfg.grp[i+1];
			i++; 
		}
		uifc.changes=1;
		continue; 
	}
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
		savgrp=*cfg.grp[i];
		continue; 
	}
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
		*cfg.grp[i]=savgrp;
		uifc.changes=1;
		continue; 
	}
	done=0;
	while(!done) {
		j=0;
		sprintf(opt[j++],"%-27.27s%s","Long Name",cfg.grp[i]->lname);
		sprintf(opt[j++],"%-27.27s%s","Short Name",cfg.grp[i]->sname);
		sprintf(opt[j++],"%-27.27s%s","Internal Code Prefix",cfg.grp[i]->code_prefix);
		sprintf(opt[j++],"%-27.27s%.40s","Access Requirements"
			,cfg.grp[i]->arstr);
		strcpy(opt[j++],"Clone Options");
		strcpy(opt[j++],"Export Areas...");
		strcpy(opt[j++],"Import Areas...");
		strcpy(opt[j++],"Message Sub-boards...");
		opt[j][0]=0;
		sprintf(str,"%s Group",cfg.grp[i]->sname);
		uifc.helpbuf=
			"`Message Group Configuration:`\n"
			"\n"
			"This menu allows you to configure the security requirements for access\n"
			"to this message group. You can also add, delete, and configure the\n"
			"sub-boards of this group by selecting the `Messages Sub-boards...` option.\n"
		;
		switch(uifc.list(WIN_ACT,6,4,60,&dflt,0,str,opt)) {
			case -1:
				done=1;
				break;
			case 0:
				uifc.helpbuf=
					"`Group Long Name:`\n"
					"\n"
					"This is a description of the message group which is displayed when a\n"
					"user of the system uses the `/*` command from the main menu.\n"
				;
				strcpy(str,cfg.grp[i]->lname);	/* save incase setting to null */
				if(!uifc.input(WIN_MID|WIN_SAV,0,17,"Name to use for Listings"
					,cfg.grp[i]->lname,LEN_GLNAME,K_EDIT))
					strcpy(cfg.grp[i]->lname,str);
				break;
			case 1:
				uifc.helpbuf=
					"`Group Short Name:`\n"
					"\n"
					"This is a short description of the message group which is used for\n"
					"main menu and reading messages prompts.\n"
				;
				uifc.input(WIN_MID|WIN_SAV,0,17,"Name to use for Prompts"
					,cfg.grp[i]->sname,LEN_GSNAME,K_EDIT);
				break;
			case 2:
				uifc.helpbuf=
					"`Internal Code Prefix:`\n"
					"\n"
					"This is an `optional` code prefix used to help generate unique internal\n"
					"codes for the sub-boards in this message group. If this option\n"
					"is used, sub-board internal codes will be constructed from this prefix\n"
					"and the specified code suffix for each sub-board.\n"
				;
				uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code Prefix"
					,cfg.grp[i]->code_prefix,LEN_CODE,K_EDIT|K_UPPER);
				break;
			case 3:
				sprintf(str,"%s Group",cfg.grp[i]->sname);
				getar(str,cfg.grp[i]->arstr);
				break;
			case 4: 	/* Clone Options */
				j=0;
				strcpy(opt[0],"Yes");
				strcpy(opt[1],"No");
				opt[2][0]=0;
				uifc.helpbuf=
					"`Clone Sub-board Options:`\n"
					"\n"
					"If you want to clone the options of the first sub-board of this group\n"
					"into all sub-boards of this group, select `Yes`.\n"
					"\n"
					"The options cloned are posting requirements, reading requirements,\n"
					"operator requirments, moderated user requirments, toggle options,\n"
					"network options (including EchoMail origin line, EchoMail address,\n"
					"and QWK Network tagline), maximum number of messages, maximum number\n"
					"of CRCs, maximum age of messages, storage method, and data directory.\n"
				;
				j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0
					,"Clone Options of First Sub-board into All of Group",opt);
				if(j==0) {
					k=-1;
					for(j=0;j<cfg.total_subs;j++)
						if(cfg.sub[j]->grp==i) {
							if(k==-1)
								k=j;
							else {
								uifc.changes=1;
								cfg.sub[j]->misc=(cfg.sub[k]->misc|SUB_HDRMOD);
								strcpy(cfg.sub[j]->post_arstr,cfg.sub[k]->post_arstr);
								strcpy(cfg.sub[j]->read_arstr,cfg.sub[k]->read_arstr);
								strcpy(cfg.sub[j]->op_arstr,cfg.sub[k]->op_arstr);
								strcpy(cfg.sub[j]->mod_arstr,cfg.sub[k]->mod_arstr);
								strcpy(cfg.sub[j]->origline,cfg.sub[k]->origline);
								strcpy(cfg.sub[j]->tagline,cfg.sub[k]->tagline);
								strcpy(cfg.sub[j]->data_dir,cfg.sub[k]->data_dir);
								strcpy(cfg.sub[j]->post_sem,cfg.sub[k]->post_sem);
								cfg.sub[j]->maxmsgs=cfg.sub[k]->maxmsgs;
								cfg.sub[j]->maxcrcs=cfg.sub[k]->maxcrcs;
								cfg.sub[j]->maxage=cfg.sub[k]->maxage;

								cfg.sub[j]->faddr=cfg.sub[k]->faddr; 
							} 
						} 
				}
				break;
			case 5:
				k=0;
				ported=0;
				q=uifc.changes;
				strcpy(opt[k++],"SUBS.TXT    (Synchronet)");
				strcpy(opt[k++],"AREAS.BBS   (MSG)");
				strcpy(opt[k++],"AREAS.BBS   (SBBSecho)");
				strcpy(opt[k++],"FIDONET.NA  (Fido)");
				opt[k][0]=0;
				uifc.helpbuf=
					"`Export Area File Format:`\n"
					"\n"
					"This menu allows you to choose the format of the area file you wish to\n"
					"export the current message group into.\n"
				;
				k=0;
				k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
					,"Export Area File Format",opt);
				if(k==-1)
					break;
				if(k==0)
					sprintf(str,"%sSUBS.TXT",cfg.ctrl_dir);
				else if(k==1)
					sprintf(str,"AREAS.BBS");
				else if(k==2)
					sprintf(str,"%sAREAS.BBS",cfg.data_dir);
				else if(k==3)
					sprintf(str,"FIDONET.NA");
				if(k && k<3)
					if(uifc.input(WIN_MID|WIN_SAV,0,0,"Uplinks"
						,str2,sizeof(str2)-1,0)<=0) {
						uifc.changes=q;
						break; 
					}
				if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename"
					,str,sizeof(str)-1,K_EDIT)<=0) {
					uifc.changes=q;
					break; 
				}
				if(fexist(str)) {
					strcpy(opt[0],"Overwrite");
					strcpy(opt[1],"Append");
					opt[2][0]=0;
					j=0;
					j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0
						,"File Exists",opt);
					if(j==-1)
						break;
					if(j==0) j=O_WRONLY|O_TRUNC;
					else	 j=O_WRONLY|O_APPEND; 
				}
				else
					j=O_WRONLY|O_CREAT;
				if((stream=fnopen(&file,str,j))==NULL) {
					sprintf(str,"Open Failure: %d (%s)"
						,errno,strerror(errno));
					uifc.msg(str);
					uifc.changes=q;
					break; 
				}
				uifc.pop("Exporting Areas...");
				for(j=0;j<cfg.total_subs;j++) {
					if(cfg.sub[j]->grp!=i)
						continue;
					ported++;
					if(k==1) {		/* AREAS.BBS *.MSG */
						sprintf(str,"%s%s%s/"
							,cfg.echomail_dir
							,cfg.grp[cfg.sub[j]->grp]->code_prefix
							,cfg.sub[j]->code_suffix);
						fprintf(stream,"%-30s %-20s %s\r\n"
							,str,stou(cfg.sub[j]->sname),str2);
						continue; 
					}
					if(k==2) {		/* AREAS.BBS SBBSecho */
						fprintf(stream,"%s%-30s %-20s %s\r\n"
							,cfg.grp[cfg.sub[j]->grp]->code_prefix
							,cfg.sub[j]->code_suffix
							,stou(cfg.sub[j]->sname)
							,str2);
						continue; 
					}
					if(k==3) {		/* FIDONET.NA */
						fprintf(stream,"%-20s %s\r\n"
							,stou(cfg.sub[j]->sname),cfg.sub[j]->lname);
						continue; 
					}
					fprintf(stream,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
							"%s\r\n%s\r\n%s\r\n"
						,cfg.sub[j]->lname
						,cfg.sub[j]->sname
						,cfg.sub[j]->qwkname
						,cfg.sub[j]->code_suffix
						,cfg.sub[j]->data_dir
						,cfg.sub[j]->arstr
						,cfg.sub[j]->read_arstr
						,cfg.sub[j]->post_arstr
						,cfg.sub[j]->op_arstr
						);
					fprintf(stream,"%"PRIX32"\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
						,cfg.sub[j]->misc
						,cfg.sub[j]->tagline
						,cfg.sub[j]->origline
						,cfg.sub[j]->post_sem
						,cfg.sub[j]->newsgroup
						,smb_faddrtoa(&cfg.sub[j]->faddr,tmp)
						);
					fprintf(stream,"%"PRIu32"\r\n%"PRIu32"\r\n%u\r\n%u\r\n%s\r\n"
						,cfg.sub[j]->maxmsgs
						,cfg.sub[j]->maxcrcs
						,cfg.sub[j]->maxage
						,cfg.sub[j]->ptridx
						,cfg.sub[j]->mod_arstr
						);
					fprintf(stream,"***END-OF-SUB***\r\n\r\n"); 
				}
				fclose(stream);
				uifc.pop(0);
				sprintf(str,"%lu Message Areas Exported Successfully",ported);
				uifc.msg(str);
				uifc.changes=q;
				break;
			case 6:
				ported=0;
				k=0;
				strcpy(opt[k++],"SUBS.TXT    (Synchronet)");
				strcpy(opt[k++],"AREAS.BBS   (Generic)");
				strcpy(opt[k++],"AREAS.BBS   (SBBSecho)");
				strcpy(opt[k++],"FIDONET.NA  (Fido)");
				opt[k][0]=0;
				uifc.helpbuf=
					"`Import Area File Format:`\n"
					"\n"
					"This menu allows you to choose the format of the area file you wish to\n"
					"import into the current message group.\n"
				;
				k=0;
				k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
					,"Import Area File Format",opt);
				if(k==-1)
					break;
				if(k==0)
					sprintf(str,"%sSUBS.TXT",cfg.ctrl_dir);
				else if(k==1)
					sprintf(str,"AREAS.BBS");
				else if(k==2)
					sprintf(str,"%sAREAS.BBS",cfg.data_dir);
				else if(k==3)
					sprintf(str,"FIDONET.NA");
				if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename"
					,str,sizeof(str)-1,K_EDIT)<=0)
                    break;
				if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
					uifc.msg("Open Failure");
                    break; 
				}
				uifc.pop("Importing Areas...");
				total_subs = cfg.total_subs;	 /* Save original number of subs */
				ptridx = 0;
				while(!feof(stream)) {
					if(!fgets(str,sizeof(str),stream)) break;
					truncsp(str);
					if(!str[0])
						continue;
					if(k) {
						p=str;
						while(*p && *p<=' ') p++;
						if(!*p || *p==';')
							continue;
						memset(&tmpsub,0,sizeof(sub_t));
						tmpsub.misc|=
							(SUB_FIDO|SUB_NAME|SUB_TOUSER|SUB_QUOTE|SUB_HYPER);
						if(k==1) {		/* AREAS.BBS Generic/*.MSG */
							p=str;
							SKIP_WHITESPACE(p);			/* Find path	*/
							FIND_WHITESPACE(p);			/* Skip path	*/
							SKIP_WHITESPACE(p);			/* Find tag		*/
							truncstr(p," \t");			/* Truncate tag */
							SAFECOPY(tmp_code,p);		/* Copy tag to internal code */
							SAFECOPY(tmpsub.lname,utos(p));
							SAFECOPY(tmpsub.sname,tmpsub.lname);
							SAFECOPY(tmpsub.qwkname,tmpsub.qwkname);
						}
						else if(k==2) { /* AREAS.BBS SBBSecho */
							p=str;
							SKIP_WHITESPACE(p);			/* Find internal code */
							tp=p;
							FIND_WHITESPACE(tp);
							*tp=0;						/* Truncate internal code */
							SAFECOPY(tmp_code,p);		/* Copy internal code suffix */
							p=tp+1;
							SKIP_WHITESPACE(p);			/* Find echo tag */
							truncstr(p," \t");			/* Truncate tag */
							SAFECOPY(tmpsub.lname,utos(p));
							SAFECOPY(tmpsub.sname,tmpsub.lname);
							SAFECOPY(tmpsub.qwkname,tmpsub.sname);
						}
						else if(k==3) { /* FIDONET.NA */
                            p=str;
							SKIP_WHITESPACE(p);			/* Find echo tag */
							tp=p;
							FIND_WHITESPACE(tp);		/* Find end of tag */
							*tp=0;						/* Truncate echo tag */
							SAFECOPY(tmp_code,p);		/* Copy tag to internal code suffix */
							SAFECOPY(tmpsub.sname,utos(p));	/* ... to short name, converting underscores to spaces */
							SAFECOPY(tmpsub.qwkname,tmpsub.sname);	/* ... to QWK name .... */
							p=tp+1;
							SKIP_WHITESPACE(p);			/* Find description */
							SAFECOPY(tmpsub.lname,p);	/* Copy description to long name */
						}
					}
					else {
						memset(&tmpsub,0,sizeof(sub_t));
						tmpsub.grp=i;
						sprintf(tmpsub.lname,"%.*s",LEN_SLNAME,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.qwkname,"%.*s",10,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						SAFECOPY(tmp_code,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.data_dir,"%.*s",LEN_DIR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.read_arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.post_arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.op_arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.misc=ahtoul(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.tagline,"%.*s",80,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.origline,"%.*s",50,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.post_sem,"%.*s",LEN_DIR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						SAFECOPY(tmpsub.newsgroup,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.faddr=atofaddr(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.maxmsgs=atol(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.maxcrcs=atol(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.maxage=atoi(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.ptridx=atoi(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.mod_arstr,"%.*s",LEN_ARSTR,str);

						while(!feof(stream)
							&& strcmp(str,"***END-OF-SUB***")) {
							if(!fgets(str,128,stream)) break;
							truncsp(str); 
						} 
					}

                    SAFECOPY(tmpsub.code_suffix, prep_code(tmp_code,cfg.grp[i]->code_prefix));
					truncsp(tmpsub.sname);
					truncsp(tmpsub.lname);
					truncsp(tmpsub.qwkname);

					if(tmpsub.code_suffix[0]==0
						|| tmpsub.sname[0]==0
						|| tmpsub.lname[0]==0
						|| tmpsub.qwkname[0]==0)
						continue;

					for(j=0;j<total_subs;j++) {
						if(cfg.sub[j]->grp!=i)
							continue;
						if(!stricmp(cfg.sub[j]->code_suffix,tmpsub.code_suffix))
							break; 
					}
					if(j==total_subs) {
						j=cfg.total_subs;
						if((cfg.sub=(sub_t **)realloc(cfg.sub
							,sizeof(sub_t *)*(cfg.total_subs+1)))==NULL) {
							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_subs+1);
							cfg.total_subs=0;
							bail(1);
							break; 
						}

						if((cfg.sub[j]=(sub_t *)malloc(sizeof(sub_t)))
							==NULL) {
							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(sub_t));
							break; 
						}
						memset(cfg.sub[j],0,sizeof(sub_t)); 
					}
					if(!k) {
						n=cfg.sub[j]->ptridx;	/* save original ptridx */
						memcpy(cfg.sub[j],&tmpsub,sizeof(sub_t));
						cfg.sub[j]->ptridx=n;	/* restore original ptridx */
					} else {
                        cfg.sub[j]->grp=i;
						if(cfg.total_faddrs)
							cfg.sub[j]->faddr=cfg.faddr[0];
						strcpy(cfg.sub[j]->code_suffix,tmpsub.code_suffix);
						strcpy(cfg.sub[j]->sname,tmpsub.sname);
						strcpy(cfg.sub[j]->lname,tmpsub.lname);
						strcpy(cfg.sub[j]->qwkname,tmpsub.qwkname);
						strcpy(cfg.sub[j]->data_dir,tmpsub.data_dir);
						if(j==cfg.total_subs)
							cfg.sub[j]->maxmsgs=1000;
					}
					if(j==cfg.total_subs) {	/* adding new sub-board */
						for(;ptridx<USHRT_MAX;ptridx++) {
							for(n=0;n<total_subs;n++)
								if(cfg.sub[n]->ptridx==ptridx)
									break;
							if(n==total_subs)
								break; 
						}
						cfg.sub[j]->ptridx=ptridx;	/* use new ptridx */
						cfg.sub[j]->misc=tmpsub.misc;
						cfg.total_subs++; 
						ptridx++;	/* don't use the same ptridx for next sub */
					}
					uifc.changes=1; 
					ported++;
				}
				fclose(stream);
				uifc.pop(0);
				sprintf(str,"%lu Message Areas Imported Successfully",ported);
                uifc.msg(str);
				break;

			case 7:
                sub_cfg(i);
				break; 
			} 
		} 
	}
}