/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_auth_timeout(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL, *ptr, *msg;
	uint16_t num;

	if (op & XMLDIFF_REM) {
		netopeer_options.ssh_opts->auth_timeout = 10;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	num = strtol(content, &ptr, 10);
	if (*ptr != '\0') {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		if (asprintf(&msg, "Could not convert '%s' to a number.", content) == 0) {
			nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
			free(msg);
		}
		return EXIT_FAILURE;
	}

	netopeer_options.ssh_opts->auth_timeout = num;
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_hello_timeout(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL, *ptr, *msg;
	uint32_t num;

	if (op & XMLDIFF_REM) {
		/* set default value */
		nc_hello_timeout(600 * 1000);
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	num = strtol(content, &ptr, 10);
	if (*ptr != '\0') {
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		if (asprintf(&msg, "Could not convert '%s' to a number.", content) == 0) {
			nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
			nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/hello-timeout");
			free(msg);
		}
		return EXIT_FAILURE;
	}

	nc_hello_timeout(num * 1000);
	return EXIT_SUCCESS;
}
Example #3
0
int
ofcds_deleteconfig(void *UNUSED(data), NC_DATASTORE target,
                   struct nc_err **error)
{
    switch (target) {
    case NC_DATASTORE_RUNNING:
        *error = nc_err_new(NC_ERR_OP_FAILED);
        nc_err_set(*error, NC_ERR_PARAM_MSG,
                   "Cannot delete a running datastore.");
        return EXIT_FAILURE;
    case NC_DATASTORE_STARTUP:
        store_rollback(gds_startup, NC_DATASTORE_STARTUP);
        gds_startup = NULL;
        break;
    case NC_DATASTORE_CANDIDATE:
        store_rollback(gds_cand, NC_DATASTORE_CANDIDATE);
        gds_cand = NULL;
        break;
    default:
        nc_verb_error("Invalid <delete-config> target.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
nc_reply* rpc_reload_module(xmlNodePtr input) {
	xmlNodePtr module_node = get_rpc_node("module", input);
	char* module_name;
	struct np_module* module = netopeer_options.modules;

	if (module_node) {
		module_name = (char*)xmlNodeGetContent(module_node);
	} else {
		return nc_reply_error(nc_err_new(NC_ERR_MISSING_ELEM));
	}

	while (module) {
		if (strcmp(module->name, module_name) == 0) {
			break;
		}
		module = module->next;
	}
	free(module_name);

	if (module == NULL) {
		return nc_reply_error(nc_err_new(NC_ERR_INVALID_VALUE));
	}

	if (module_disable(module, 0) || module_enable(module, 0)) {
		return nc_reply_error(nc_err_new(NC_ERR_OP_FAILED));
	}

	return nc_reply_ok();
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_max_sessions(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL, *ptr, *msg;
	uint16_t num;

	if (op & XMLDIFF_REM) {
		netopeer_options.max_sessions = 8;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	num = strtol(content, &ptr, 10);
	if (*ptr != '\0') {
		asprintf(&msg, "Could not convert '%s' to a number.", content);
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
		nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/max-sessions");
		free(msg);
		return EXIT_FAILURE;
	}

	netopeer_options.max_sessions = num;
	return EXIT_SUCCESS;
}
Example #6
0
int
ofcds_unlock(void *UNUSED(data), NC_DATASTORE target, const char *session_id,
             struct nc_err **error)
{
    int *locked;
    char **sid;

    switch (target) {
    case NC_DATASTORE_RUNNING:
        locked = &(locks.running);
        sid = &(locks.running_sid);
        break;
    case NC_DATASTORE_STARTUP:
        locked = &(locks.startup);
        sid = &(locks.startup_sid);
        break;
    case NC_DATASTORE_CANDIDATE:
        locked = &(locks.cand);
        sid = &(locks.cand_sid);
        break;
    default:
        /* handled by libnetconf */
        return EXIT_FAILURE;
    }

    if (*locked) {
        if (strcmp(*sid, session_id) == 0) {
            /* correct request, unlock */
            *locked = 0;
            free(*sid);
            *sid = NULL;
            nc_verb_verbose("OFC datastore %d unlocked by %s.", target,
                            session_id);
        } else {
            /* locked by another session */
            *error = nc_err_new(NC_ERR_LOCK_DENIED);
            nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid);
            nc_err_set(*error, NC_ERR_PARAM_MSG,
                       "Target datastore is locked by another session.");
            return EXIT_FAILURE;
        }
    } else {
        /* not locked */
        *error = nc_err_new(NC_ERR_OP_FAILED);
        nc_err_set(*error, NC_ERR_PARAM_MSG,
                   "Target datastore is not locked.");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_server_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* key = NULL, *type = NULL;
	xmlNodePtr child;

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		for (child = new_node->children; child != NULL; child = child->next) {
			if (xmlStrEqual(child->name, BAD_CAST "key-data")) {
				key = get_node_content(child);
			}

			if (xmlStrEqual(child->name, BAD_CAST "key-type")) {
				type = get_node_content(child);
			}
		}

		if (key == NULL || type == NULL) {
			*error = nc_err_new(NC_ERR_MISSING_ELEM);
			nc_err_set(*error, NC_ERR_PARAM_MSG, "key-data and/or key-type element missing.");
			return EXIT_FAILURE;
		}

		if (strcmp(type, "RSA") != 0 && strcmp(type, "DSA") != 0) {
			*error = nc_err_new(NC_ERR_BAD_ELEM);
			nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/tls/server-key/key-type");
			return EXIT_FAILURE;
		}
	}

	/* TLS_CTX LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

	free(netopeer_options.tls_opts->server_key);
	netopeer_options.tls_opts->server_key = NULL;
	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		netopeer_options.tls_opts->server_key = strdup(key);
		if (strcmp(type, "RSA") == 0) {
			netopeer_options.tls_opts->server_key_type = 1;
		} else {
			netopeer_options.tls_opts->server_key_type = 0;
		}
	}
	netopeer_options.tls_opts->tls_ctx_change_flag = 1;

	/* TLS_CTX UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_crl_dir(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}
	}

	/* CRL_DIR LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->crl_dir_lock);

	free(netopeer_options.tls_opts->crl_dir);
	netopeer_options.tls_opts->crl_dir = NULL;
	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		netopeer_options.tls_opts->crl_dir = strdup(content);
	}

	/* CRL_DIR UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->crl_dir_lock);

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_server_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}
	}

	/* TLS_CTX LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

	free(netopeer_options.tls_opts->server_cert);
	netopeer_options.tls_opts->server_cert = NULL;
	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		netopeer_options.tls_opts->server_cert = strdup(content);
	}
	netopeer_options.tls_opts->tls_ctx_change_flag = 1;

	/* TLS_CTX UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);

	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_trusted_ca_certs_n_trusted_ca_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		content = get_node_content(old_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}

		/* TLS_CTX LOCK */
		pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

		if (del_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0) != 0) {
			nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__);
		} else {
			netopeer_options.tls_opts->tls_ctx_change_flag = 1;
		}

		/* TLS_CTX UNLOCK */
		pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);
	}

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}

		/* TLS_CTX LOCK */
		pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

		add_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0);
		netopeer_options.tls_opts->tls_ctx_change_flag = 1;

		/* TLS_CTX UNLOCK */
		pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);
	}

	return EXIT_SUCCESS;
}
nc_reply* rpc_netopeer_reboot(xmlNodePtr input) {
	xmlNodePtr type_node = get_rpc_node("type", input);
	char* type_str = NULL;

	if (type_node) {
		type_str = (char*)xmlNodeGetContent(type_node);
	}

	if (type_str == NULL || strcmp(type_str, "soft") == 0) {
		restart_soft = 1;
	} else if (strcmp(type_str, "hard") == 0) {
		quit = 1;
		restart_hard = 1;
	} else {
		free(type_str);
		return nc_reply_error(nc_err_new(NC_ERR_INVALID_VALUE));
	}
	free(type_str);

	return nc_reply_ok();
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_password_auth_enabled(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & XMLDIFF_REM) {
		netopeer_options.ssh_opts->password_auth_enabled = 1;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	if (strcmp(content, "false") == 0) {
		netopeer_options.ssh_opts->password_auth_enabled = 0;
	} else {
		netopeer_options.ssh_opts->password_auth_enabled = 1;
	}
	return EXIT_SUCCESS;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_server_keys_n_dsa_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & XMLDIFF_REM) {
		free(netopeer_options.ssh_opts->dsa_key);
		netopeer_options.ssh_opts->dsa_key = NULL;
		netopeer_options.ssh_opts->server_key_change_flag = 1;
		return EXIT_SUCCESS;
	}

	content = get_node_content(new_node);
	if (content == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: node content missing", __func__);
		return EXIT_FAILURE;
	}

	free(netopeer_options.ssh_opts->dsa_key);
	netopeer_options.ssh_opts->dsa_key = strdup(content);
	netopeer_options.ssh_opts->server_key_change_flag = 1;
	return EXIT_SUCCESS;
}
Example #14
0
int
ofcds_lock(void *UNUSED(data), NC_DATASTORE target, const char *session_id,
           struct nc_err **error)
{
    int *locked;
    char **sid;

    switch (target) {
    case NC_DATASTORE_RUNNING:
        locked = &(locks.running);
        sid = &(locks.running_sid);
        break;
    case NC_DATASTORE_STARTUP:
        locked = &(locks.startup);
        sid = &(locks.startup_sid);
        break;
    case NC_DATASTORE_CANDIDATE:
        locked = &(locks.cand);
        sid = &(locks.cand_sid);
        break;
    default:
        /* handled by libnetconf */
        return EXIT_FAILURE;
    }

    if (*locked) {
        /* datastore is already locked */
        *error = nc_err_new(NC_ERR_LOCK_DENIED);
        nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid);
        return EXIT_FAILURE;
    } else {
        /* remember the lock */
        *locked = 1;
        *sid = strdup(session_id);
        nc_verb_verbose("OFC datastore %d locked by %s.", target, session_id);
    }

    return EXIT_SUCCESS;
}
Example #15
0
/**
 * @brief Parse the given reply message and create a NETCONF error structure
 * describing the error from the reply. Reply must be of the #NC_REPLY_ERROR type.
 * @param[in] reply \<rpc-reply\> message to be parsed.
 * @return Filled error structure according to the given rpc-reply, it is up to the
 * caller to free the structure using nc_err_free().
 */
struct nc_err* nc_err_parse(nc_reply* reply)
{
	xmlXPathObjectPtr result = NULL;
	xmlNodePtr node, subnode;
	int i;
	struct nc_err* e = NULL, *eaux = NULL;

	if (reply == NULL || reply->doc == NULL || reply->type.reply != NC_REPLY_ERROR) {
		return (NULL);
	}
	if (reply->error != NULL) {
		/* error structure is already created */
		return (reply->error);
	}

	/* find all <rpc-error>s */
	result = xmlXPathEvalExpression(BAD_CAST "/"NC_NS_BASE10_ID":rpc-reply/"NC_NS_BASE10_ID":rpc-error", reply->ctxt);
	if (result != NULL) {
		for (i = 0; i < result->nodesetval->nodeNr; i++) {
			/* error structure is not yet created */
			eaux = nc_err_new(NC_ERR_EMPTY);

			/* parse the content of the message */
			for (node = result->nodesetval->nodeTab[i]->children;
			                node != NULL; node = node->next) {
				if (node->type != XML_ELEMENT_NODE || node->ns == NULL || strcmp(NC_NS_BASE10, (char*)(node->ns->href)) != 0) {
					continue;
				}
				if (xmlStrcmp(node->name, BAD_CAST "error-tag") == 0) {
					eaux->tag = (char*) xmlNodeGetContent(node);
				} else if (xmlStrcmp(node->name, BAD_CAST "error-type") == 0) {
					eaux->type = (char*) xmlNodeGetContent(node);
				} else if (xmlStrcmp(node->name, BAD_CAST "error-severity") == 0) {
					eaux->severity = (char*) xmlNodeGetContent(node);
				} else if (xmlStrcmp(node->name, BAD_CAST "error-app-tag") == 0) {
					eaux->apptag = (char*) xmlNodeGetContent(node);
				} else if (xmlStrcmp(node->name, BAD_CAST "error-path") == 0) {
					eaux->path = (char*) xmlNodeGetContent(node);
				} else if (xmlStrcmp(node->name, BAD_CAST "error-message") == 0) {
					eaux->message = (char*) xmlNodeGetContent(node);
				} else if (xmlStrcmp(node->name, BAD_CAST "error-info") == 0) {
					subnode = node->children;
					while (subnode != NULL) {
						if (subnode->type != XML_ELEMENT_NODE || subnode->ns == NULL || strcmp(NC_NS_BASE10, (char*)(subnode->ns->href)) != 0) {
							subnode = subnode->next;
							continue;
						}
						if (xmlStrcmp(subnode->name, BAD_CAST "bad-attribute") == 0) {
							eaux->attribute = (char*) xmlNodeGetContent(subnode);
						} else if (xmlStrcmp(subnode->name, BAD_CAST "bad-element") == 0 ||
								xmlStrcmp(subnode->name, BAD_CAST "ok-element") == 0 ||
								xmlStrcmp(subnode->name, BAD_CAST "err-element") == 0 ||
								xmlStrcmp(subnode->name, BAD_CAST "noop-element") == 0) {
							eaux->element = (char*) xmlNodeGetContent(subnode);
						} else if (xmlStrcmp(subnode->name, BAD_CAST "bad-namespace") == 0) {
							eaux->ns = (char*) xmlNodeGetContent(subnode);
						} else if (xmlStrcmp(subnode->name, BAD_CAST "session-id") == 0) {
							eaux->sid = (char*) xmlNodeGetContent(subnode);
						}
						subnode = subnode->next;
					}
				}
			}

			if (e != NULL) {
				/* concatenate multiple rpc-errors in repl-reply */
				eaux->next = e;
			}
			e = eaux;
		}
		xmlXPathFreeObject(result);
	} else {
		ERROR("No error information in the reply message to parse.");
		/* NULL, which is default e's value, will be returned */
	}

	/* store the result for the further use */
	//reply->error = nc_err_dup(e);
	reply->error = e;

	return (e);
}
Example #16
0
static PyObject *ncProcessRPC(ncSessionObject *self)
{
	NC_MSG_TYPE ret;
	NC_RPC_TYPE req_type;
	NC_OP req_op;
	nc_rpc *rpc = NULL;
	nc_reply *reply = NULL;
	struct nc_err* e = NULL;

	SESSION_CHECK(self);

	/* receive incoming message */
	ret = nc_session_recv_rpc(self->session, -1, &rpc);
	if (ret != NC_MSG_RPC) {
		if (nc_session_get_status(self->session) != NC_SESSION_STATUS_WORKING) {
			/* something really bad happend, and communication is not possible anymore */
			nc_session_free(self->session);
			self->session = NULL;
		}
		Py_RETURN_NONE;
	}

	/* process it */
	req_type = nc_rpc_get_type(rpc);
	req_op = nc_rpc_get_op(rpc);
	if (req_type == NC_RPC_SESSION) {
		/* process operations affectinf session */
		switch(req_op) {
		case NC_OP_CLOSESESSION:
			/* exit the event loop immediately without processing any following request */
			reply = nc_reply_ok();
			break;
		case NC_OP_KILLSESSION:
			/* todo: kill the requested session */
			reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED));
			break;
		default:
			reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED));
			break;
		}
	} else if (req_type == NC_RPC_DATASTORE_READ) {
		/* process operations reading datastore */
		switch (req_op) {
		case NC_OP_GET:
		case NC_OP_GETCONFIG:
			reply = ncds_apply_rpc2all(self->session, rpc,  NULL);
			break;
		default:
			reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED));
			break;
		}
	} else if (req_type == NC_RPC_DATASTORE_WRITE) {
		/* process operations affecting datastore */
		switch (req_op) {
		case NC_OP_LOCK:
		case NC_OP_UNLOCK:
		case NC_OP_COPYCONFIG:
		case NC_OP_DELETECONFIG:
		case NC_OP_EDITCONFIG:
			reply = ncds_apply_rpc2all(self->session, rpc, NULL);
			break;
		default:
			reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED));
			break;
		}
	} else {
		/* process other operations */
		reply = ncds_apply_rpc2all(self->session, rpc, NULL);
	}

	/* create reply */
	if (reply == NULL) {
		reply = nc_reply_error(nc_err_new(NC_ERR_OP_FAILED));
	} else if (reply == NCDS_RPC_NOT_APPLICABLE) {
		e = nc_err_new(NC_ERR_OP_FAILED);
		nc_err_set(e, NC_ERR_PARAM_MSG, "Requested operation cannot be performed on the managed datastore.");
		reply = nc_reply_error(e);
	}

	/* and send the reply to the client */
	nc_session_send_reply(self->session, rpc, reply);
	nc_rpc_free(rpc);
	nc_reply_free(reply);

	if (req_op == NC_OP_CLOSESESSION) {
		/* free the Session */
		nc_session_free(self->session);
		self->session = NULL;
	}

	Py_RETURN_NONE;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_cert_maps_n_cert_to_name(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	char* id = NULL, *fingerprint = NULL, *map_type = NULL, *name = NULL, *ptr, *msg;
	xmlNodePtr child;

callback_restart:
	for (child = (op & (XMLDIFF_MOD | XMLDIFF_REM) ? old_node->children : new_node->children); child != NULL; child = child->next) {
		if (xmlStrEqual(child->name, BAD_CAST "id")) {
			id = get_node_content(child);
		}
		if (xmlStrEqual(child->name, BAD_CAST "fingerprint")) {
			fingerprint = get_node_content(child);
		}
		if (xmlStrEqual(child->name, BAD_CAST "map-type")) {
			map_type = get_node_content(child);
			if (strchr(map_type, ':') != NULL) {
				map_type = strchr(map_type, ':')+1;
			}
		}
		if (xmlStrEqual(child->name, BAD_CAST "name")) {
			name = get_node_content(child);
		}
	}

	if (id == NULL || fingerprint == NULL || map_type == NULL) {
		*error = nc_err_new(NC_ERR_MISSING_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_MSG, "id and/or fingerprint and/or map-type element missing.");
		return EXIT_FAILURE;
	}
	strtol(id, &ptr, 10);
	if (*ptr != '\0') {
		asprintf(&msg, "Could not convert '%s' to a number.", id);
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/tls/cert-maps/cert-to-name/id");
		nc_err_set(*error, NC_ERR_PARAM_MSG, msg);
		free(msg);
		return EXIT_FAILURE;
	}
	if (strcmp(map_type, "specified") == 0 && name == NULL) {
		*error = nc_err_new(NC_ERR_MISSING_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_MSG, "name element missing.");
		return EXIT_FAILURE;
	}

	/* CTN_MAP LOCK */
	pthread_mutex_lock(&netopeer_options.tls_opts->ctn_map_lock);

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		if (del_ctn_item(&netopeer_options.tls_opts->ctn_map, atoi(id), fingerprint, ctn_type_parse(map_type), name) != 0) {
			nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__);
		}

		if (op & XMLDIFF_MOD) {
			/* CTN_MAP UNLOCK */
			pthread_mutex_unlock(&netopeer_options.tls_opts->ctn_map_lock);
			op = XMLDIFF_ADD;
			goto callback_restart;
		}
	}
	if (op & XMLDIFF_ADD) {
		add_ctn_item(&netopeer_options.tls_opts->ctn_map, atoi(id), fingerprint, ctn_type_parse(map_type), name);
	}

	/* CTN_MAP UNLOCK */
	pthread_mutex_unlock(&netopeer_options.tls_opts->ctn_map_lock);

	return EXIT_SUCCESS;
}
Example #18
0
int
ofcds_editconfig(void *UNUSED(data), const nc_rpc * UNUSED(rpc),
                 NC_DATASTORE target, const char *config,
                 NC_EDIT_DEFOP_TYPE defop,
                 NC_EDIT_ERROPT_TYPE UNUSED(errop), struct nc_err **error)
{
    int ret = EXIT_FAILURE, running = 0;
    char *aux;
    int cfgds_new = 0;
    xmlDocPtr cfgds = NULL, cfg = NULL, cfg_clone = NULL;
    xmlNodePtr rootcfg;

    if (defop == NC_EDIT_DEFOP_NOTSET) {
        defop = NC_EDIT_DEFOP_MERGE;
    }

    cfg = xmlReadMemory(config, strlen(config), NULL, NULL, XML_READ_OPT);
    rootcfg = xmlDocGetRootElement(cfg);
    if (!cfg
        || (rootcfg
            && !xmlStrEqual(rootcfg->name, BAD_CAST "capable-switch"))) {
        nc_verb_error("Invalid <edit-config> configuration data.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "config");
        return EXIT_FAILURE;
    }

    switch (target) {
    case NC_DATASTORE_RUNNING:
        /* Make a copy of parsed config - we will find port/configuration in
         * it.  It is used after txn_commit(). */
        cfg_clone = xmlCopyDoc(cfg, 1);

        aux = ofc_get_config_data();
        if (!aux) {
            *error = nc_err_new(NC_ERR_OP_FAILED);
            goto error_cleanup;
        }
        cfgds = xmlReadMemory(aux, strlen(aux), NULL, NULL, XML_READ_OPT);
        free(aux);

        running = 1;
        break;
    case NC_DATASTORE_STARTUP:
        cfgds = gds_startup;
        break;
    case NC_DATASTORE_CANDIDATE:
        cfgds = gds_cand;
        break;
    default:
        nc_verb_error("Invalid <edit-config> target.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target");
        goto error_cleanup;
    }
    store_rollback(xmlCopyDoc(cfgds, 1), target);

    /* check keys in config's lists */
    ret = check_keys(cfg, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }

    /* check operations */
    ret = check_edit_ops(NC_EDIT_OP_DELETE, defop, cfgds, cfg, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }
    ret = check_edit_ops(NC_EDIT_OP_CREATE, defop, cfgds, cfg, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }

    if (target == NC_DATASTORE_RUNNING) {
        txn_init();
    }

    ret = compact_edit_operations(cfg, defop);
    if (ret != EXIT_SUCCESS) {
        nc_verb_error("Compacting edit-config operations failed.");
        if (error != NULL) {
            *error = nc_err_new(NC_ERR_OP_FAILED);
        }
        goto error_cleanup;
    }

    /* perform operations */
    if (!cfgds) {
        cfgds_new = 1;
        cfgds = xmlNewDoc(BAD_CAST "1.0");
    }
    ret = edit_operations(cfgds, cfg, defop, running, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }

    /* with defaults capability */
    if (ncdflt_get_basic_mode() == NCWD_MODE_TRIM) {
        /* server work in trim basic mode and therefore all default values
         * must be removed from the datastore. */
        /* TODO */
    }

    if (target == NC_DATASTORE_RUNNING) {
        ret = txn_commit(error);

        if (ret == EXIT_SUCCESS) {
            /* modify port/configuration of ports that were created */
            ret = of_post_ports(xmlDocGetRootElement(cfg_clone), error);
        }
        /* config clone was used and it is not needed by now */
        xmlFreeDoc(cfg_clone);

        xmlFreeDoc(cfgds);
    } else if (cfgds_new){
        if (cfgds->children) {
            /* document changed, because we started with empty document */
            if (target == NC_DATASTORE_STARTUP) {
                gds_startup = cfgds;
                cfgds = NULL;
            } else if (target == NC_DATASTORE_CANDIDATE) {
                gds_cand = cfgds;
                cfgds = NULL;
            }
        }
        xmlFreeDoc(cfgds);
    }
    xmlFreeDoc(cfg);

    return ret;

error_cleanup:

    if (target == NC_DATASTORE_RUNNING) {
        txn_abort();
        xmlFreeDoc(cfg_clone);
        xmlFreeDoc(cfgds);
    }
    xmlFreeDoc(cfg);

    return ret;
}
Example #19
0
int
ofcds_copyconfig(void *UNUSED(data), NC_DATASTORE target,
                 NC_DATASTORE source, char *config, struct nc_err **error)
{
    int ret = EXIT_FAILURE;
    char *s;
    xmlDocPtr src_doc = NULL;
    xmlDocPtr dst_doc = NULL;
    xmlNodePtr root;
    static const char *ds[] = {"error", "<config>", "URL", "running",
                               "startup", "candidate"};

    nc_verb_verbose("OFC COPY-CONFIG (from %s to %s)", ds[source], ds[target]);

    switch (source) {
    case NC_DATASTORE_RUNNING:
        s = ofcds_getconfig(NULL, NC_DATASTORE_RUNNING, error);
        if (!s) {
            nc_verb_error
                ("copy-config: unable to get running source repository");
            return EXIT_FAILURE;
        }
        src_doc = xmlReadMemory(s, strlen(s), NULL, NULL, XML_READ_OPT);
        free(s);
        if (!src_doc) {
            nc_verb_error("copy-config: invalid running source data");
            *error = nc_err_new(NC_ERR_OP_FAILED);
            nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM,
                       "invalid running source data");
            return EXIT_FAILURE;
        }
        break;
    case NC_DATASTORE_STARTUP:
        src_doc = xmlCopyDoc(gds_startup, 1);
        break;
    case NC_DATASTORE_CANDIDATE:
        src_doc = xmlCopyDoc(gds_cand, 1);
        break;
    case NC_DATASTORE_CONFIG:
        if (config && strlen(config) > 0) {
            src_doc = xmlReadMemory(config, strlen(config), NULL, NULL,
                                    XML_READ_OPT);
        }
        if (!config || (strlen(config) > 0 && !src_doc)) {
            nc_verb_error("Invalid source configuration data.");
            *error = nc_err_new(NC_ERR_BAD_ELEM);
            nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "config");
            return EXIT_FAILURE;
        }

        break;
    default:
        nc_verb_error("Invalid <get-config> source.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source");
        return EXIT_FAILURE;
    }

    switch (target) {
    case NC_DATASTORE_RUNNING:
        /* apply source to OVSDB */

        s = ofcds_getconfig(NULL, NC_DATASTORE_RUNNING, error);
        if (!s) {
            nc_verb_error("copy-config: unable to get running source data");
            goto cleanup;
        }
        dst_doc = xmlReadMemory(s, strlen(s), NULL, NULL, XML_READ_OPT);
        free(s);

        root = xmlDocGetRootElement(src_doc);
        if (!dst_doc) {
            /* create envelope */
            dst_doc = xmlNewDoc(BAD_CAST "1.0");
        }
        if (!rollbacking) {
            store_rollback(xmlCopyDoc(dst_doc, 1), target);
        }

        txn_init();
        if (edit_replace(dst_doc, root, 1, error)) {
            txn_abort();
        } else {
            ret = txn_commit(error);
        }
        xmlFreeDoc(dst_doc);
        goto cleanup;
        break;
    case NC_DATASTORE_STARTUP:
    case NC_DATASTORE_CANDIDATE:
        /* create copy */
        if (src_doc) {
            dst_doc = src_doc;
            src_doc = NULL;
        }

        /* store the copy */
        if (target == NC_DATASTORE_STARTUP) {
            if (!rollbacking) {
                store_rollback(gds_startup, target);
            } else {
                xmlFreeDoc(gds_startup);
            }
            gds_startup = dst_doc;
        } else {                /* NC_DATASTORE_CANDIDATE */
            if (!rollbacking) {
                store_rollback(gds_cand, target);
            } else {
                xmlFreeDoc(gds_cand);
            }
            gds_cand = dst_doc;
        }

        break;
    default:
        nc_verb_error("Invalid <get-config> source.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source");
        goto cleanup;
    }

    ret = EXIT_SUCCESS;

cleanup:
    xmlFreeDoc(src_doc);

    return ret;
}
/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_ssh_n_client_auth_keys_n_client_auth_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	xmlNodePtr node;
	char* path = NULL, *username = NULL;
	struct np_auth_key* key;

	if (op & XMLDIFF_REM) {
		node = old_node;
	} else {
		node = new_node;
	}

	for (node = node->children; node != NULL; node = node->next) {
		if (xmlStrEqual(node->name, BAD_CAST "path")) {
			path = get_node_content(node);
		}
		if (xmlStrEqual(node->name, BAD_CAST "username")) {
			username = get_node_content(node);
		}
	}

	if (path == NULL || username == NULL) {
		*error = nc_err_new(NC_ERR_OP_FAILED);
		nc_verb_error("%s: path and/or username missing", __func__);
		return EXIT_FAILURE;
	}

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		for (key = netopeer_options.ssh_opts->client_auth_keys; key != NULL; key = key->next) {
			if (strcmp(key->path, path) == 0) {
				break;
			}
		}

		if (key == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: internal error: changed key not found", __func__);
			return EXIT_FAILURE;
		}

		/* CLIENT KEYS LOCK */
		pthread_mutex_lock(&netopeer_options.ssh_opts->client_keys_lock);

		/* remove the key */
		if (op & XMLDIFF_REM) {
			if (key->prev == NULL) {
				netopeer_options.ssh_opts->client_auth_keys = key->next;
				free(key->path);
				free(key->username);
				free(key);
				if (netopeer_options.ssh_opts->client_auth_keys != NULL) {
					netopeer_options.ssh_opts->client_auth_keys->prev = NULL;
				}
			} else {
				key->prev->next = key->next;
				if (key->next != NULL) {
					key->next->prev = key->prev;
				}
				free(key->path);
				free(key->username);
				free(key);
			}

		/* modify the key */
		} else {
			free(key->username);
			key->username = strdup(username);
		}

		/* CLIENT KEYS UNLOCK */
		pthread_mutex_unlock(&netopeer_options.ssh_opts->client_keys_lock);

	} else if (op & XMLDIFF_ADD) {

		/* CLIENT KEYS LOCK */
		pthread_mutex_lock(&netopeer_options.ssh_opts->client_keys_lock);

		/* add the key */
		if (netopeer_options.ssh_opts->client_auth_keys == NULL) {
			netopeer_options.ssh_opts->client_auth_keys = calloc(1, sizeof(struct np_auth_key));
			netopeer_options.ssh_opts->client_auth_keys->path = strdup(path);
			netopeer_options.ssh_opts->client_auth_keys->username = strdup(username);
		} else {
			for (key = netopeer_options.ssh_opts->client_auth_keys; key->next != NULL; key = key->next) {
				key->next = calloc(1, sizeof(struct np_auth_key));
				key->path = strdup(path);
				key->username = strdup(username);
				key->next->prev = key;
			}
		}

		/* CLIENT KEYS UNLOCK */
		pthread_mutex_unlock(&netopeer_options.ssh_opts->client_keys_lock);
	}


	return EXIT_SUCCESS;
}
Example #21
0
int ncds_custom_lock(struct ncds_ds* ds, const struct nc_session* session, NC_DATASTORE target, struct nc_err** error) {
	int retval, localinfo = 0;
	const char *sid = NULL;
	struct ncds_ds_custom *c_ds = (struct ncds_ds_custom *) ds;
	struct ncds_lockinfo *linfo;
	pthread_mutex_t* linfo_mut = NULL;

	linfo = get_lockinfo(target, &linfo_mut);
	if (linfo == NULL) {
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target");
		return (EXIT_FAILURE);
	}

	pthread_mutex_lock(linfo_mut);
	if (c_ds->callbacks->is_locked == NULL) {
		/* is_locked() is not implemented by custom datastore, use local info */
		localinfo = 1;
		if (linfo->sid != NULL) {
			/* datastore is already locked */
			retval = 1;
			sid = linfo->sid;
		} else {
			retval = 0;
		}
	} else {
		/* take locking access into custom datastore plugin */
		sem_wait(cds_lock); /* localinfo = 0 */

		/* get current info using is_locked() */
		retval = c_ds->callbacks->is_locked(c_ds->data, target, &sid, NULL);
		if (retval < 0) { /* error */
			sem_post(cds_lock);
			pthread_mutex_unlock(linfo_mut);
			ERROR("%s: custom datastore's is_locked() function failed (error %d)", __func__, retval);
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_err_set(*error, NC_ERR_PARAM_MSG, "custom datastore's is_locked() function failed");
			return (EXIT_FAILURE);
		}
	}

	/* check current status of the lock */
	if (retval == 0 || localinfo) {
		/* datastore is not locked (or we are not sure), try to lock it */
		retval = c_ds->callbacks->lock(c_ds->data, target, session->session_id, error);
	} else { /* retval == 1 && localinfo == 0 */
		/* datastore is already locked */
		*error = nc_err_new(NC_ERR_LOCK_DENIED);
		nc_err_set(*error, NC_ERR_PARAM_INFO_SID, sid);
		retval = EXIT_FAILURE;
	}

	/* drop locking access into custom datastore plugin */
	if (localinfo == 0) {
		sem_post(cds_lock);
	}

	/* update localinfo structure */
	if (retval == EXIT_SUCCESS) {
		linfo->time = nc_time2datetime(time(NULL), NULL);
		linfo->sid = strdup(session->session_id);
	}

	pthread_mutex_unlock(linfo_mut);
	return (retval);
}
Example #22
0
int ncds_custom_unlock(struct ncds_ds* ds, const struct nc_session* session, NC_DATASTORE target, struct nc_err** error) {
	int retval, localinfo = 0;
	const char *sid = NULL;
	struct ncds_ds_custom *c_ds = (struct ncds_ds_custom *) ds;
	struct ncds_lockinfo *linfo;
	pthread_mutex_t* linfo_mut = NULL;

	linfo = get_lockinfo(target, &linfo_mut);
	if (linfo == NULL) {
		*error = nc_err_new(NC_ERR_BAD_ELEM);
		nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target");
		return (EXIT_FAILURE);
	}

	pthread_mutex_lock(linfo_mut);
	if (c_ds->callbacks->is_locked == NULL) {
		/* is_locked() is not implemented by custom datastore, so we will
		 * try to use local info */
		localinfo = 1;
		if (linfo->sid == NULL) {
			/* datastore is not locked */
			retval = 0;
		} else {
			retval = 1;
			sid = linfo->sid;
		}
	} else {
		/* take locking access into custom datastore plugin */
		sem_wait(cds_lock); /* localinfo = 0 */

		/* get current info using is_locked() */
		retval = c_ds->callbacks->is_locked(c_ds->data, target, &sid, NULL);
		if (retval < 0) { /* error */
			sem_post(cds_lock);
			pthread_mutex_unlock(linfo_mut);
			ERROR("%s: custom datastore's is_locked() function failed (error %d)", __func__, retval);
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_err_set(*error, NC_ERR_PARAM_MSG, "custom datastore's is_locked() function failed");
			return (EXIT_FAILURE);
		}
	}

	if (retval == 0) {
		if (localinfo) {
			/* try to call custom's unlock() if our info was up-to-date */
			retval = c_ds->callbacks->unlock(c_ds->data, target, session->session_id, error);
			/* if unlock succeeded, we were wrong and operation succeeds */
		} else {
			/* datastore is not locked */
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is not locked.");
			retval = EXIT_FAILURE;
		}
	} else { /* retval == 1 */
		/* datastore is locked, check that we can unlock it and do it */
		if (strcmp(sid, session->session_id) != 0) {
			if (localinfo) {
				/* try to call custom's unlock() if our info was up-to-date */
				retval = c_ds->callbacks->unlock(c_ds->data, target, session->session_id, error);
				/* if unlock succeeded, we were wrong and operation succeeds */
			} else {
				/* datastore is locked by someone else */
				*error = nc_err_new(NC_ERR_OP_FAILED);
				nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is locked by another session.");
				retval = EXIT_FAILURE;
			}
		} else {
			/* try to unlock the datastore */
			retval = c_ds->callbacks->unlock(c_ds->data, target, session->session_id, error);
		}
	}

	/* drop locking access into custom datastore plugin */
	if (localinfo == 0) {
		sem_post(cds_lock);
	}

	if (retval == EXIT_SUCCESS) {
		free(linfo->time);
		free(linfo->sid);
		linfo->time = NULL;
		linfo->sid = NULL;
	}

	pthread_mutex_unlock(linfo_mut);
	return (retval);
}
Example #23
-1
char *
ofcds_getconfig(void *UNUSED(data), NC_DATASTORE target, struct nc_err **error)
{
    xmlChar *config_data = NULL;

    switch (target) {
    case NC_DATASTORE_RUNNING:
        /* If there is no id of the capable-switch (no configuration data were
         * provided), continue as there is no OVSDB */
        return ofc_get_config_data();
    case NC_DATASTORE_STARTUP:
        if (!gds_startup) {
            config_data = xmlStrdup(BAD_CAST "");
        } else {
            xmlDocDumpMemory(gds_startup, &config_data, NULL);
        }
        break;
    case NC_DATASTORE_CANDIDATE:
        if (!gds_cand) {
            config_data = xmlStrdup(BAD_CAST "");
        } else {
            xmlDocDumpMemory(gds_cand, &config_data, NULL);
        }
        break;
    default:
        nc_verb_error("Invalid <get-config> source.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source");
    }

    return (char *) config_data;
}