Example #1
0
smcp_status_t
resend_pair_request(char* url[2]) {
	smcp_status_t status;
#if SMCP_ENABLE_PAIRING
	coap_size_t len = 8;
	bool did_mutate = false;
	while(url[0][len] && url[0][len]!='/') {
		len++;
	}

	// Temporarily mutate the input url because I'm lazy.
	if(url[0][len]) {
		did_mutate = true;
		url[0][len] = 0;
	}

	status = smcp_outbound_begin(
		smcp_get_current_instance(),
		COAP_METHOD_PUT,
		COAP_TRANS_TYPE_CONFIRMABLE
	);
	require_noerr(status,bail);

	status = smcp_outbound_set_uri(url[0],0);
	require_noerr(status,bail);

	// Root pairings object path
	status = smcp_outbound_add_option(COAP_OPTION_URI_PATH,SMCP_PAIRING_DEFAULT_ROOT_PATH,SMCP_CSTR_LEN);
	require_noerr(status,bail);

	// Path to pair with
	status = smcp_outbound_add_option(COAP_OPTION_URI_PATH,url[0]+len+1,SMCP_CSTR_LEN);
	require_noerr(status,bail);

	// Remote target
	status = smcp_outbound_add_option(COAP_OPTION_URI_PATH,url[1],SMCP_CSTR_LEN);
	require_noerr(status,bail);

	status = smcp_outbound_send();
	require_noerr(status,bail);
bail:
	if(did_mutate) {
		url[0][len] = '/';
	}
#else
	status = SMCP_STATUS_NOT_IMPLEMENTED;
#endif
	return status;
}
Example #2
0
smcp_status_t
smcp_outbound_add_option_uint(coap_option_key_t key,uint32_t value) {
	uint8_t size;

	value = htonl(value);
	size = smcp_calc_uint32_option_size(value);

	return smcp_outbound_add_option(key, ((char*)&value)+(4-size), size);
}
Example #3
0
smcp_status_t
smcp_auth_verify_request() {
	smcp_status_t ret = SMCP_STATUS_OK;
	coap_option_key_t key;
	const uint8_t* authvalue;
	size_t authvalue_len;

	// For testing purposes only!
	if(smcp_inbound_get_code() >1 && smcp_inbound_get_code()<COAP_RESULT_100) {
		ret = SMCP_STATUS_UNAUTHORIZED;
	}

	smcp_inbound_reset_next_option();

	while((key = smcp_inbound_next_option(&authvalue,&authvalue_len))!=COAP_OPTION_INVALID) {
		if(key==COAP_OPTION_PROXY_URI) {
			// For testing purposes only!
			ret = SMCP_STATUS_OK;
		}
		if(key==COAP_OPTION_AUTHENTICATE) {
			// For testing purposes only!
			ret = SMCP_STATUS_OK;
			// writeme!
		}
	}

	if(smcp_inbound_origin_is_local()) {
		ret = SMCP_STATUS_OK;
	}

	ret = SMCP_STATUS_OK;

	// For testing purposes only!
	if(ret==SMCP_STATUS_UNAUTHORIZED) {
		smcp_outbound_begin_response(COAP_RESULT_401_UNAUTHORIZED);
		smcp_outbound_add_option(COAP_OPTION_AUTHENTICATE,NULL,0);
		smcp_outbound_send();
	}

	return ret;
}
Example #4
0
smcp_status_t
smcp_auth_outbound_set_credentials(const char* username, const char* password) {
	smcp_status_t ret = SMCP_STATUS_OK;

	// TODO: Writeme!
	smcp_auth_user_t auth_user = smcp_auth_get_remote_user(username);
	//struct smcp_auth_nonce_s *auth_nonce;

	if(!auth_user) {
		require(username,bail);

		// Just do something stupid for now.
		ret = smcp_outbound_add_option(COAP_OPTION_AUTHENTICATE, NULL, 0);

		require(password,bail);

		auth_user = &global_temp_auth_user;

		smcp_auth_user_set(auth_user,username,password,"");
	}

bail:
	return ret;
}
Example #5
0
smcp_status_t
smcp_outbound_add_option_uint(coap_option_key_t key,uint32_t value) {
	if(value>>24)
		return value = htonl(value),smcp_outbound_add_option(key, ((char*)&value)+0, 4);
	else if(value>>16)
Example #6
0
smcp_status_t
smcp_outbound_set_uri(
	const char* uri, char flags
) {
	smcp_status_t ret = SMCP_STATUS_OK;
	smcp_t const self = smcp_get_current_instance();
	SMCP_NON_RECURSIVE struct url_components_s components;
	SMCP_NON_RECURSIVE uint16_t toport;
	SMCP_NON_RECURSIVE char* uri_copy;

	memset((void*)&components, 0, sizeof(components));
	toport = COAP_DEFAULT_PORT;
	smcp_plat_set_session_type(SMCP_SESSION_TYPE_UDP);
	uri_copy = NULL;

	require_action(uri, bail, ret = SMCP_STATUS_INVALID_ARGUMENT);

	{
#if HAVE_ALLOCA
		uri_copy = alloca(strlen(uri) + 1);
		strcpy(uri_copy, uri);
#elif SMCP_AVOID_MALLOC
		// Well, we can't use the stack and we can't
		// use malloc. Let's use what room we have left
		// in the packet buffer, since this is temporary anyway...
		// It helps a bunch that we know the user hasn't written
		// any content yet (because that would be an API violation)
		if (smcp_outbound_get_space_remaining() > strlen(uri) + 8) {
			uri_copy = self->outbound.content_ptr + self->outbound.content_len;

			// The options section may be expanding as we parse this, so
			// we should move ahead by a few bytes. We are helped out
			// by the fact that we will be writing the options in the
			// same order they appear in the URL.
			uri_copy += 8;

			strcpy(uri_copy, uri);
		}
#else
		uri_copy = strdup(uri);
#endif

		require_action(uri_copy != NULL, bail, ret = SMCP_STATUS_MALLOC_FAILURE);

		// Parse the URI.
		require_action_string(
			url_parse(
				uri_copy,
				&components
			),
			bail,
			ret = SMCP_STATUS_URI_PARSE_FAILURE,
			"Unable to parse URL"
		);

		if(!components.protocol && !components.host) {
			// Talking to ourself.
			components.protocol = "coap";
			components.host = "::1";
			toport = smcp_plat_get_port(smcp_get_current_instance());
			flags |= SMCP_MSG_SKIP_AUTHORITY;
		} else if(components.port) {
			toport = (uint16_t)atoi(components.port);
		}

		DEBUG_PRINTF(
			"URI Parse: \"%s\" -> host=\"%s\" port=\"%u\" path=\"%s\"",
			uri,
			components.host,
			toport,
			components.path
		);
	}

	if (components.protocol) {
		smcp_session_type_t session_type = smcp_session_type_from_uri_scheme(components.protocol);
		smcp_plat_set_session_type(session_type);

		if (NULL == components.port) {
			toport = smcp_default_port_from_session_type(session_type);
		}

		if (session_type == SMCP_SESSION_TYPE_NIL) {
			require_action_string(
				self->proxy_url,
				bail,
				ret=SMCP_STATUS_INVALID_ARGUMENT,
				"No proxy URL configured"
			);
			require_action(uri != self->proxy_url,bail,ret = SMCP_STATUS_INVALID_ARGUMENT);

			ret = smcp_outbound_add_option(COAP_OPTION_PROXY_URI, uri, SMCP_CSTR_LEN);
			require_noerr(ret, bail);
			ret = smcp_outbound_set_uri(self->proxy_url,flags);
			goto bail;
		}
	}

	if (!(flags & SMCP_MSG_SKIP_AUTHORITY)) {
		if(components.host && !string_contains_colons(components.host)) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_HOST, components.host, SMCP_CSTR_LEN);
			require_noerr(ret, bail);
		}
		if(components.port) {
			ret = smcp_outbound_add_option_uint(COAP_OPTION_URI_PORT, toport);
			require_noerr(ret, bail);
		}
	}


	if ( !(flags & SMCP_MSG_SKIP_DESTADDR)
	  && components.host && components.host[0]!=0
	) {
		ret = smcp_set_remote_sockaddr_from_host_and_port(
			components.host,
			toport
		);
		require_noerr(ret, bail);
	}

	if (components.path) {
		SMCP_NON_RECURSIVE char* component;
		const bool has_trailing_slash = components.path[0]?('/' == components.path[strlen(components.path)-1]):false;

		// Move past any preceding slashes.
		while (components.path[0] == '/') {
			components.path++;
		}

		while (url_path_next_component(&components.path,&component)) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_PATH, component, SMCP_CSTR_LEN);
			require_noerr(ret,bail);
		}

		if (has_trailing_slash) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_PATH, NULL, 0);
			require_noerr(ret,bail);
		}
	}

	if (components.query) {
		SMCP_NON_RECURSIVE char* key;

		while (url_form_next_value(&components.query, &key, NULL)) {
			coap_size_t len = (coap_size_t)strlen(key);

			if (len) {
				ret = smcp_outbound_add_option(COAP_OPTION_URI_QUERY, key, len);
			}
			require_noerr(ret,bail);
		}
	}

bail:
	if(ret) {
		DEBUG_PRINTF("URI Parse failed for URI: \"%s\"",uri);
	}

#if !HAVE_ALLOCA && !SMCP_AVOID_MALLOC
	free(uri_copy);
#endif

	return ret;
}
Example #7
0
static smcp_status_t
request_handler_new_group_(
	smcp_group_mgr_t self
) {
	smcp_status_t ret = SMCP_STATUS_OK;
	coap_content_type_t content_type;
	coap_size_t content_len;
	char* fqdn = NULL;
	char* addr_cstr = NULL;
	smcp_sockaddr_t saddr = { };
	char* content_ptr = NULL;
	char* key = NULL;
	char* value = NULL;
	smcp_group_t group = NULL;
	char name_str[3] = { };

	content_type = smcp_inbound_get_content_type();
	content_ptr = (char*)smcp_inbound_get_content_ptr();
	content_len = smcp_inbound_get_content_len();

	switch (content_type) {
	case COAP_CONTENT_TYPE_UNKNOWN:
	case COAP_CONTENT_TYPE_TEXT_PLAIN:
	case SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED:
		content_len = 0;
		while(
			url_form_next_value(
				(char**)&content_ptr,
				&key,
				&value
			)
			&& key
			&& value
		) {

			if (strequal_const(key, names[I_FQDN])) {
				fqdn = value;
				DEBUG_PRINTF("new_group: fqdn=\"%s\"", value);
			} else if (strequal_const(key, names[I_ADDR])) {
				addr_cstr = value;
				DEBUG_PRINTF("new_group: addr=\"%s\"", value);
			}
		}
		break;

	default:
		return smcp_outbound_quick_response(HTTP_RESULT_CODE_UNSUPPORTED_MEDIA_TYPE, NULL);
		break;
	}

	if (NULL == addr_cstr) {
		require_action(NULL != fqdn, bail, ret = SMCP_STATUS_INVALID_ARGUMENT);
		addr_cstr = fqdn;
	} else if (NULL == fqdn) {
		fqdn = addr_cstr;
	}

	smcp_plat_lookup_hostname(addr_cstr, &saddr, SMCP_LOOKUP_HOSTNAME_FLAG_DEFAULT);

	group = smcp_group_mgr_new_group(
		self,
		fqdn,
		&saddr.smcp_addr,
		0
	);

	if (!group) {
		return smcp_outbound_quick_response(COAP_RESULT_400_BAD_REQUEST, "(400) Failed to create group");
	}

	// Default to enabled.
	smcp_group_set_enabled(group, true);

	name_str[0] = get_hex_char(group->index >> 4);
	name_str[1] = get_hex_char(group->index >> 0);

	smcp_outbound_begin_response(COAP_RESULT_201_CREATED);
	smcp_outbound_add_option(COAP_OPTION_LOCATION_PATH, name_str, SMCP_CSTR_LEN);
	smcp_outbound_append_content(name_str, SMCP_CSTR_LEN);
	smcp_outbound_send();

bail:
	return ret;
}