コード例 #1
0
ファイル: auth.c プロジェクト: WuKongQC/opensips
int uac_auth( struct sip_msg *msg)
{
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	struct uac_credential *crd;
	int code, branch;
	unsigned int new_cseq;
	struct sip_msg *rpl;
	struct cell *t;
	HASHHEX response;
	str *new_hdr;
	str param;
	char *p;
	struct dlg_cell *dlg;

	/* get transaction */
	t = uac_tmb.t_gett();
	if (t==T_UNDEFINED || t==T_NULL_CELL)
	{
		LM_CRIT("no current transaction found\n");
		goto error;
	}

	/* get the selected branch */
	branch = uac_tmb.t_get_picked();
	if (branch<0) {
		LM_CRIT("no picked branch (%d)\n",branch);
		goto error;
	}

	rpl = t->uac[branch].reply;
	code = t->uac[branch].last_received;
	LM_DBG("picked reply is %p, code %d\n",rpl,code);

	if (rpl==0)
	{
		LM_CRIT("empty reply on picked branch\n");
		goto error;
	}
	if (rpl==FAKED_REPLY)
	{
		LM_ERR("cannot process a FAKED reply\n");
		goto error;
	}

	if (code==WWW_AUTH_CODE) {
		if (0 == parse_www_authenticate_header(rpl))
			auth = get_www_authenticate(rpl);
	} else if (code==PROXY_AUTH_CODE) {
		if (0 == parse_proxy_authenticate_header(rpl))
			auth = get_proxy_authenticate(rpl);
	}

	if (auth == NULL) {
		LM_ERR("Unable to extract authentication info\n");
		goto error;
	}

	/* can we authenticate this realm? */
	/* look into existing credentials */
	crd = uac_auth_api._lookup_realm( &auth->realm );
	/* found? */
	if (crd==0)
	{
		LM_DBG("no credential for realm \"%.*s\"\n",
			auth->realm.len, auth->realm.s);
		goto error;
	}

	/* do authentication */
	uac_auth_api._do_uac_auth( &msg->first_line.u.request.method,
			&t->uac[branch].uri, crd, auth, &auth_nc_cnonce, response);

	/* build the authorization header */
	new_hdr = uac_auth_api._build_authorization_hdr( code, &t->uac[branch].uri,
		crd, auth, &auth_nc_cnonce, response);
	if (new_hdr==0)
	{
		LM_ERR("failed to build authorization hdr\n");
		goto error;
	}

	/* so far, so good -> add the header and set the proper RURI */
	if (apply_urihdr_changes( msg, &t->uac[branch].uri, new_hdr)<0)
	{
		LM_ERR("failed to apply changes\n");
		pkg_free(new_hdr->s);
		new_hdr->s = NULL; new_hdr->len = 0;
		goto error;
	}

	if ( (new_cseq = apply_cseq_op(msg,1)) < 0) {
		LM_WARN("Failure to increment the CSEQ header - continue \n");
		goto error;
	}

	/* only register the TMCB once per transaction */
	if (!(msg->msg_flags & FL_USE_UAC_CSEQ || 
	t->uas.request->msg_flags & FL_USE_UAC_CSEQ)) {
		if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_FWDED,
		apply_cseq_decrement,0,0)!=1) {
			LM_ERR("Failed to register TMCB response fwded - continue \n");
			goto error;
		}
	}

	if (dlg_api.get_dlg && (dlg = dlg_api.get_dlg())) {
		/* dlg->legs[dlg->legs_no[DLG_LEGS_USED]-1].last_gen_cseq = new_cseq; */
		dlg->flags |= DLG_FLAG_CSEQ_ENFORCE;
	} else {
		param.len=rr_uac_cseq_param.len+3;
		param.s=pkg_malloc(param.len);
		if (!param.s) {
			LM_ERR("No more pkg mem \n");
			goto error;
		}

		p = param.s;
		*p++=';';
		memcpy(p,rr_uac_cseq_param.s,rr_uac_cseq_param.len);
		p+=rr_uac_cseq_param.len;
		*p++='=';
		*p++='1';

		if (uac_rrb.add_rr_param( msg, &param)!=0) {
			LM_ERR("add_RR_param failed\n");
			pkg_free(param.s);
			goto error;
		}

		pkg_free(param.s);
	}

	msg->msg_flags |= FL_USE_UAC_CSEQ;
	t->uas.request->msg_flags |= FL_USE_UAC_CSEQ;

	return 0;
error:
	return -1;
}
コード例 #2
0
ファイル: registrant.c プロジェクト: mtulio/mtulio
void reg_tm_cback(struct cell *t, int type, struct tmcb_params *ps)
{
	struct sip_msg *msg;
	reg_tm_cb_t *cb_param;
	int statuscode = 0;
	unsigned int exp = 0;
	reg_record_t *rec;
	struct hdr_field *c_ptr, *head_contact;
	struct uac_credential crd;
	contact_t *contact;
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	HASHHEX response;
	str *new_hdr;
	time_t now;

	if(ps==NULL || ps->rpl==NULL) {
		LM_ERR("wrong ps parameter\n");
		return;
	}
	if(ps->param==NULL || *ps->param==NULL) {
		LM_ERR("null callback parameter\n");
		return;
	}
	cb_param = (reg_tm_cb_t *)*ps->param;
	if(cb_param->uac == NULL) {
		LM_ERR("null record\n");
		return;
	}
	statuscode = ps->code;
	now = time(0);
	LM_DBG("tm [%p] notification cb for %s [%d] reply at [%d]\n",
			t, (ps->rpl==FAKED_REPLY)?"FAKED_REPLY":"", statuscode, (unsigned int)now);

	if(statuscode<200) return;

	lock_get(&reg_htable[cb_param->hash_index].lock);
	rec = reg_htable[cb_param->hash_index].first;
	while(rec) {
		if (rec==cb_param->uac) {
			break;
		}
		rec = rec->next;
	}
	if(!rec) {
		LM_ERR("record [%p] not found on hash index [%d]\n",
		cb_param->uac, cb_param->hash_index);
		lock_release(&reg_htable[cb_param->hash_index].lock);
		return;
	}
	reg_print_record(rec);

	switch(statuscode) {
	case 200:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
			LM_ERR("failed to parse headers\n");
			goto done;
		}
		if (msg->contact) {
			c_ptr = msg->contact;
			while(c_ptr) {
				if (c_ptr->type == HDR_CONTACT_T) {
					if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) {
						LM_ERR("failed to parse Contact body\n");
						goto done;
					}
				}
				c_ptr = c_ptr->next;
			}
		} else {
			LM_ERR("No contact header in received 200ok\n");
			goto done;
		}
		head_contact = msg->contact;
		contact = ((contact_body_t*)msg->contact->parsed)->contacts;
		while (contact) {
			/* Check for binding */
			if (contact->uri.len==rec->contact_uri.len &&
				strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){
				if (contact->expires && contact->expires->body.len) {
					if (str2int(&contact->expires->body, &exp)<0) {
						LM_ERR("Unable to extract expires from [%.*s]"
							" for binding [%.*s]\n",
							contact->expires->body.len,
							contact->expires->body.s,
							contact->uri.len, contact->uri.s);
					} else {
						rec->expires = exp;
					}
				}
				break;
			}
					
			/* get the next contact */
			if (contact->next == NULL) {
				contact = NULL;
				c_ptr = head_contact->next;
				while(c_ptr) {
					if (c_ptr->type == HDR_CONTACT_T) {
						head_contact = c_ptr;
						contact = ((contact_body_t*)c_ptr->parsed)->contacts;
						break;
					}
					c_ptr = c_ptr->next;
				}
			} else {
				contact = contact->next;
			}
		}
		rec->state = REGISTERED_STATE;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	case WWW_AUTH_CODE:
	case PROXY_AUTH_CODE:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}

		if (rec->auth_user.s==NULL || rec->auth_user.len==0 ||
			rec->auth_password.s==NULL || rec->auth_password.len==0) {
			LM_ERR("Credentials not provisioned\n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			lock_release(&reg_htable[cb_param->hash_index].lock);
			return;
		}

		if (statuscode==WWW_AUTH_CODE) {
			if (0 == parse_www_authenticate_header(msg))
				auth = get_www_authenticate(msg);
		} else if (statuscode==PROXY_AUTH_CODE) {
			if (0 == parse_proxy_authenticate_header(msg))
				auth = get_proxy_authenticate(msg);
		}
		if (auth == NULL) {
			LM_ERR("Unable to extract authentication info\n");
			goto done;
		}
		LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]"
			" opaque=[%.*s] qop=[%.*s]\n",
			auth->flags,
			auth->realm.len, auth->realm.s,
			auth->domain.len, auth->domain.s,
			auth->nonce.len, auth->nonce.s,
			auth->opaque.len, auth->opaque.s,
			auth->qop.len, auth->qop.s);

		switch(rec->state) {
		case REGISTERING_STATE:
			break;
		case AUTHENTICATING_STATE:
			/* We already sent an authenticated REGISTER and we are still challanged! */
			LM_ERR("Wrong credentials for \n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			lock_release(&reg_htable[cb_param->hash_index].lock);
			return;
		default:
			LM_ERR("Unexpected [%d] notification cb in state [%d]\n",
				statuscode, rec->state);
			goto done;
		}

		/* perform authentication */
		if (auth->realm.s && auth->realm.len) {
			crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len;
		} else {
			LM_ERR("No realm found\n");
			goto done;
		}
		crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len;
		crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len;

		memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce));
		uac_auth_api._do_uac_auth(&register_method, &rec->td.rem_target, &crd,
					auth, &auth_nc_cnonce, response);
		new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target,
					&crd, auth, &auth_nc_cnonce, response);
		if (!new_hdr) {
			LM_ERR("failed to build authorization hdr\n");
			goto done;
		}
		if(send_register(cb_param->hash_index, rec, new_hdr)==1) {
			rec->state = AUTHENTICATING_STATE;
		} else {
			rec->state = INTERNAL_ERROR_STATE;
		}
		break;

	default:
		if(statuscode<400 && statuscode>=300) {
			LM_ERR("Redirection not implemented yet\n");
			rec->state = INTERNAL_ERROR_STATE;
		} else {
			/* we got an error from the server */
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
			
		}
	}

	lock_release(&reg_htable[cb_param->hash_index].lock);

	return;
done:
	rec->state = INTERNAL_ERROR_STATE;
	rec->registration_timeout = now + rec->expires;
	lock_release(&reg_htable[cb_param->hash_index].lock);
	return;
}
コード例 #3
0
ファイル: proxy.c プロジェクト: ThomasHabets/openvpn
bool
establish_http_proxy_passthru (struct http_proxy_info *p,
			       socket_descriptor_t sd, /* already open to proxy */
			       const char *host,       /* openvpn server remote */
			       const int port,         /* openvpn server port */
			       struct buffer *lookahead,
			       volatile int *signal_received)
{
  struct gc_arena gc = gc_new ();
  char buf[512];
  char buf2[128];
  char get[80];
  int status;
  int nparms;
  bool ret = false;
  bool processed = false;

  /* get user/pass if not previously given */
  if (p->auth_method == HTTP_AUTH_BASIC
      || p->auth_method == HTTP_AUTH_DIGEST
      || p->auth_method == HTTP_AUTH_NTLM)
    get_user_pass_http (p, false);

  /* are we being called again after getting the digest server nonce in the previous transaction? */
  if (p->auth_method == HTTP_AUTH_DIGEST && p->proxy_authenticate)
    {
      nparms = 1;
      status = 407;
    }
  else
    {
      /* format HTTP CONNECT message */
      openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
			host,
			port,
			p->options.http_version);

      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);

      /* send HTTP CONNECT message to proxy */
      if (!send_line_crlf (sd, buf))
	goto error;

      openvpn_snprintf(buf, sizeof(buf), "Host: %s", host);
      if (!send_line_crlf(sd, buf))
        goto error;

      /* send User-Agent string if provided */
      if (p->options.user_agent)
	{
	  openvpn_snprintf (buf, sizeof(buf), "User-Agent: %s",
			    p->options.user_agent);
	  if (!send_line_crlf (sd, buf))
	    goto error;
	}

      /* auth specified? */
      switch (p->auth_method)
	{
	case HTTP_AUTH_NONE:
	  break;

	case HTTP_AUTH_BASIC:
	  openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Basic %s",
			    username_password_as_base64 (p, &gc));
	  msg (D_PROXY, "Attempting Basic Proxy-Authorization");
	  dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
	  if (!send_line_crlf (sd, buf))
	    goto error;
	  break;

#if NTLM
	case HTTP_AUTH_NTLM:
	case HTTP_AUTH_NTLM2:
	  /* keep-alive connection */
	  openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
	  if (!send_line_crlf (sd, buf))
	    goto error;

	  openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s",
			    ntlm_phase_1 (p, &gc));
	  msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 1");
	  dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
	  if (!send_line_crlf (sd, buf))
	    goto error;
	  break;
#endif

	default:
	  ASSERT (0);
	}

      /* send empty CR, LF */
      if (!send_crlf (sd))
	goto error;

      /* receive reply from proxy */
      if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
	goto error;

      /* remove trailing CR, LF */
      chomp (buf);

      msg (D_PROXY, "HTTP proxy returned: '%s'", buf);

      /* parse return string */
      nparms = sscanf (buf, "%*s %d", &status);

    }

  /* check for a "407 Proxy Authentication Required" response */
  while (nparms >= 1 && status == 407)
    {
      msg (D_PROXY, "Proxy requires authentication");

      if (p->auth_method == HTTP_AUTH_BASIC && !processed)
	{
	  processed = true;
	}
      else if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) /* check for NTLM */
        {
#if NTLM
          /* look for the phase 2 response */

          while (true)
            {
              if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
                goto error;
              chomp (buf);
              msg (D_PROXY, "HTTP proxy returned: '%s'", buf);

              openvpn_snprintf (get, sizeof get, "%%*s NTLM %%%ds", (int) sizeof (buf2) - 1);
              nparms = sscanf (buf, get, buf2);
              buf2[127] = 0; /* we only need the beginning - ensure it's null terminated. */

              /* check for "Proxy-Authenticate: NTLM TlRM..." */
              if (nparms == 1)
                {
                  /* parse buf2 */
                  msg (D_PROXY, "auth string: '%s'", buf2);
                  break;
                }
            }
          /* if we are here then auth string was got */
          msg (D_PROXY, "Received NTLM Proxy-Authorization phase 2 response");

          /* receive and discard everything else */
          while (recv_line (sd, NULL, 0, 2, true, NULL, signal_received))
            ;

          /* now send the phase 3 reply */

          /* format HTTP CONNECT message */
          openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
			    host,
			    port,
			    p->options.http_version);

          msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);

          /* send HTTP CONNECT message to proxy */
          if (!send_line_crlf (sd, buf))
            goto error;

          /* keep-alive connection */
          openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
          if (!send_line_crlf (sd, buf))
            goto error;

          
          /* send HOST etc, */
          openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
          msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
          if (!send_line_crlf (sd, buf))
            goto error;

          msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3");
	  {
	    const char *np3 = ntlm_phase_3 (p, buf2, &gc);
	    if (!np3)
	      {
		msg (D_PROXY, "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
		goto error;
	      }
	    openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", np3);
	  }

          msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
          if (!send_line_crlf (sd, buf))
	    goto error;
          /* ok so far... */
          /* send empty CR, LF */
          if (!send_crlf (sd))
            goto error;

          /* receive reply from proxy */
          if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
            goto error;

          /* remove trailing CR, LF */
          chomp (buf);

          msg (D_PROXY, "HTTP proxy returned: '%s'", buf);

          /* parse return string */
          nparms = sscanf (buf, "%*s %d", &status);
	  processed = true;
#endif
	}
#if PROXY_DIGEST_AUTH
      else if (p->auth_method == HTTP_AUTH_DIGEST && !processed)
	{
	  char *pa = p->proxy_authenticate;
	  const int method = p->auth_method;
	  ASSERT(pa);

	  if (method == HTTP_AUTH_DIGEST)
	    {
	      const char *http_method = "CONNECT";
	      const char *nonce_count = "00000001";
	      const char *qop = "auth";
	      const char *username = p->up.username;
	      const char *password = p->up.password;
	      char *opaque_kv = "";
	      char uri[128];
	      uint8_t cnonce_raw[8];
	      uint8_t *cnonce;
	      HASHHEX session_key;
	      HASHHEX response;

	      const char *realm = get_pa_var("realm", pa, &gc);
	      const char *nonce = get_pa_var("nonce", pa, &gc);
	      const char *algor = get_pa_var("algorithm", pa, &gc);
	      const char *opaque = get_pa_var("opaque", pa, &gc);

	      /* generate a client nonce */
	      ASSERT(rand_bytes(cnonce_raw, sizeof(cnonce_raw)));
	      cnonce = make_base64_string2(cnonce_raw, sizeof(cnonce_raw), &gc);


	      /* build the digest response */
	      openvpn_snprintf (uri, sizeof(uri), "%s:%d",
				host,
				port);

	      if (opaque)
		{
		  const int len = strlen(opaque)+16;
		  opaque_kv = gc_malloc(len, false, &gc);
		  openvpn_snprintf (opaque_kv, len, ", opaque=\"%s\"", opaque);
		}

	      DigestCalcHA1(algor,
			    username,
			    realm,
			    password,
			    nonce,
			    (char *)cnonce,
			    session_key);
	      DigestCalcResponse(session_key,
				 nonce,
				 nonce_count,
				 (char *)cnonce,
				 qop,
				 http_method,
				 uri,
				 NULL,
				 response);

	      /* format HTTP CONNECT message */
	      openvpn_snprintf (buf, sizeof(buf), "%s %s HTTP/%s",
				http_method,
				uri,
				p->options.http_version);

	      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);

	      /* send HTTP CONNECT message to proxy */
	      if (!send_line_crlf (sd, buf))
		goto error;

	      /* send HOST etc, */
	      openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
	      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
	      if (!send_line_crlf (sd, buf))
		goto error;

	      /* send digest response */
	      openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
				username,
				realm,
				nonce,
				uri,
				qop,
				nonce_count,
				cnonce,
				response,
				opaque_kv
				);
	      msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
	      if (!send_line_crlf (sd, buf))
		goto error;
	      if (!send_crlf (sd))
		goto error;

	      /* receive reply from proxy */
	      if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
		goto error;

	      /* remove trailing CR, LF */
	      chomp (buf);

	      msg (D_PROXY, "HTTP proxy returned: '%s'", buf);

	      /* parse return string */
	      nparms = sscanf (buf, "%*s %d", &status);
	      processed = true;
	    }
	  else
	    {
	      msg (D_PROXY, "HTTP proxy: digest method not supported");
	      goto error;
	    }
	}
#endif
      else if (p->options.auth_retry)
	{
	  /* figure out what kind of authentication the proxy needs */
	  char *pa = NULL;
	  const int method = get_proxy_authenticate(sd,
						    p->options.timeout,
						    &pa,
						    NULL,
						    signal_received);
	  if (method != HTTP_AUTH_NONE)
	    {
	      if (pa)
		msg (D_PROXY, "HTTP proxy authenticate '%s'", pa);
	      if (p->options.auth_retry == PAR_NCT && method == HTTP_AUTH_BASIC)
		{
		  msg (D_PROXY, "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
		  goto error;
		}
	      p->auth_method = method;
	      store_proxy_authenticate(p, pa);
	      ret = true;
	      goto done;
	    }
	  else
	    {
	      msg (D_PROXY, "HTTP proxy: do not recognize the authentication method required by proxy");
	      free (pa);
	      goto error;
	    }
	}
      else
	{
	  if (!processed)
	    msg (D_PROXY, "HTTP proxy: no support for proxy authentication method");
	  goto error;
	}

      /* clear state */
      if (p->options.auth_retry)
	clear_user_pass_http();
      store_proxy_authenticate(p, NULL);
    }

  /* check return code, success = 200 */
  if (nparms < 1 || status != 200)
    {
      msg (D_LINK_ERRORS, "HTTP proxy returned bad status");
#if 0
      /* DEBUGGING -- show a multi-line HTTP error response */
      dump_residual(sd, p->options.timeout, signal_received);
#endif
      goto error;
    }

  /* SUCCESS */

  /* receive line from proxy and discard */
  if (!recv_line (sd, NULL, 0, p->options.timeout, true, NULL, signal_received))
    goto error;

  /*
   * Toss out any extraneous chars, but don't throw away the
   * start of the OpenVPN data stream (put it in lookahead).
   */
  while (recv_line (sd, NULL, 0, 2, false, lookahead, signal_received))
    ;

  /* reset queried_creds so that we don't think that the next creds request is due to an auth error */
  p->queried_creds = false;

#if 0
  if (lookahead && BLEN (lookahead))
    msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0));
#endif

 done:
  gc_free (&gc);
  return ret;

 error:
  /* on error, should we exit or restart? */
  if (!*signal_received)
    *signal_received = (p->options.retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- HTTP proxy error */
  gc_free (&gc);
  return ret;
}
コード例 #4
0
ファイル: registrant.c プロジェクト: KISSMonX/opensips
int run_reg_tm_cback(void *e_data, void *data, void *r_data)
{
	struct sip_msg *msg;
	int statuscode = 0;
	unsigned int exp = 0;
	reg_record_t *rec = (reg_record_t*)e_data;
	struct hdr_field *c_ptr, *head_contact;
	struct uac_credential crd;
	contact_t *contact;
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	HASHHEX response;
	str *new_hdr;
	struct reg_tm_cback_data *tm_cback_data = (struct reg_tm_cback_data*)data;
	struct cell *t;
	struct tmcb_params *ps;
	time_t now;
	reg_tm_cb_t *cb_param;

	cb_param = tm_cback_data->cb_param;
	if (rec!=cb_param->uac) {
		/* no action on current list elemnt */
		return 0; /* continue list traversal */
	}

	t = tm_cback_data->t;
	ps = tm_cback_data->ps;
	now = tm_cback_data->now;

	reg_print_record(rec);

	if (ps->rpl==FAKED_REPLY)
		memset(&rec->td.forced_to_su, 0, sizeof(union sockaddr_union));
	else if (rec->td.forced_to_su.s.sa_family == AF_UNSPEC)
		rec->td.forced_to_su = t->uac[0].request.dst.to;

	statuscode = ps->code;
	switch(statuscode) {
	case 200:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
			LM_ERR("failed to parse headers\n");
			goto done;
		}
		if (msg->contact) {
			c_ptr = msg->contact;
			while(c_ptr) {
				if (c_ptr->type == HDR_CONTACT_T) {
					if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) {
						LM_ERR("failed to parse Contact body\n");
						goto done;
					}
				}
				c_ptr = c_ptr->next;
			}
		} else {
			LM_ERR("No contact header in received 200ok\n");
			goto done;
		}
		head_contact = msg->contact;
		contact = ((contact_body_t*)msg->contact->parsed)->contacts;
		while (contact) {
			/* Check for binding */
			if (contact->uri.len==rec->contact_uri.len &&
				strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){
				if (contact->expires && contact->expires->body.len) {
					if (str2int(&contact->expires->body, &exp)<0) {
						LM_ERR("Unable to extract expires from [%.*s]"
							" for binding [%.*s]\n",
							contact->expires->body.len,
							contact->expires->body.s,
							contact->uri.len, contact->uri.s);
					}
				}
				break;
			}
					
			/* get the next contact */
			if (contact->next == NULL) {
				contact = NULL;
				c_ptr = head_contact->next;
				while(c_ptr) {
					if (c_ptr->type == HDR_CONTACT_T) {
						head_contact = c_ptr;
						contact = ((contact_body_t*)c_ptr->parsed)->contacts;
						break;
					}
					c_ptr = c_ptr->next;
				}
			} else {
				contact = contact->next;
			}
		}
		rec->state = REGISTERED_STATE;
		if (exp) rec->expires = exp;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	case WWW_AUTH_CODE:
	case PROXY_AUTH_CODE:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}

		if (rec->auth_user.s==NULL || rec->auth_user.len==0 ||
			rec->auth_password.s==NULL || rec->auth_password.len==0) {
			LM_ERR("Credentials not provisioned\n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			/* action successfuly completed on current list element */
			return 1; /* exit list traversal */
		}

		if (statuscode==WWW_AUTH_CODE) {
			if (0 == parse_www_authenticate_header(msg))
				auth = get_www_authenticate(msg);
		} else if (statuscode==PROXY_AUTH_CODE) {
			if (0 == parse_proxy_authenticate_header(msg))
				auth = get_proxy_authenticate(msg);
		}
		if (auth == NULL) {
			LM_ERR("Unable to extract authentication info\n");
			goto done;
		}
		LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]"
			" opaque=[%.*s] qop=[%.*s]\n",
			auth->flags,
			auth->realm.len, auth->realm.s,
			auth->domain.len, auth->domain.s,
			auth->nonce.len, auth->nonce.s,
			auth->opaque.len, auth->opaque.s,
			auth->qop.len, auth->qop.s);

		switch(rec->state) {
		case REGISTERING_STATE:
			break;
		case AUTHENTICATING_STATE:
			/* We already sent an authenticated REGISTER and we are still challanged! */
			LM_WARN("Wrong credentials for [%.*s]\n",
				rec->td.rem_uri.len, rec->td.rem_uri.s);
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			/* action successfuly completed on current list element */
			return 1; /* exit list traversal */
		default:
			LM_ERR("Unexpected [%d] notification cb in state [%d]\n",
				statuscode, rec->state);
			goto done;
		}

		/* perform authentication */
		if (auth->realm.s && auth->realm.len) {
			crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len;
		} else {
			LM_ERR("No realm found\n");
			goto done;
		}
		crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len;
		crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len;

		memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce));
		uac_auth_api._do_uac_auth(&register_method, &rec->td.rem_target, &crd,
					auth, &auth_nc_cnonce, response);
		new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target,
					&crd, auth, &auth_nc_cnonce, response);
		if (!new_hdr) {
			LM_ERR("failed to build authorization hdr\n");
			goto done;
		}
		if(send_register(cb_param->hash_index, rec, new_hdr)==1) {
			rec->state = AUTHENTICATING_STATE;
		} else {
			rec->state = INTERNAL_ERROR_STATE;
		}
		pkg_free(new_hdr->s);
		new_hdr->s = NULL; new_hdr->len = 0;
		break;

	case 423: /* Interval Too Brief */
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (0 == parse_min_expires(msg)) {
			rec->expires = (unsigned int)(long)msg->min_expires->parsed;
			if(send_register(cb_param->hash_index, rec, NULL)==1)
				rec->state = REGISTERING_STATE;
			else
				rec->state = INTERNAL_ERROR_STATE;
		} else {
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
		}
		break;

	case 408: /* Interval Too Brief */
		rec->state = REGISTER_TIMEOUT_STATE;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	default:
		if(statuscode<400 && statuscode>=300) {
			LM_ERR("Redirection not implemented yet\n");
			rec->state = INTERNAL_ERROR_STATE;
		} else {
			/* we got an error from the server */
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
			
		}
	}

	/* action successfuly completed on current list element */
	return 1; /* exit list traversal */
done:
	rec->state = INTERNAL_ERROR_STATE;
	rec->registration_timeout = now + rec->expires;
	return -1; /* exit list traversal */
}
コード例 #5
0
ファイル: auth.c プロジェクト: UIKit0/OpenSIPS
int uac_auth( struct sip_msg *msg)
{
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	struct uac_credential *crd;
	int code, branch;
	struct sip_msg *rpl;
	struct cell *t;
	HASHHEX response;
	str *new_hdr;

	/* get transaction */
	t = uac_tmb.t_gett();
	if (t==T_UNDEFINED || t==T_NULL_CELL)
	{
		LM_CRIT("no current transaction found\n");
		goto error;
	}

	/* get the selected branch */
	branch = uac_tmb.t_get_picked();
	if (branch<0) {
		LM_CRIT("no picked branch (%d)\n",branch);
		goto error;
	}

	rpl = t->uac[branch].reply;
	code = t->uac[branch].last_received;
	LM_DBG("picked reply is %p, code %d\n",rpl,code);

	if (rpl==0)
	{
		LM_CRIT("empty reply on picked branch\n");
		goto error;
	}
	if (rpl==FAKED_REPLY)
	{
		LM_ERR("cannot process a FAKED reply\n");
		goto error;
	}

	if (code==WWW_AUTH_CODE) {
		if (0 == parse_www_authenticate_header(rpl))
			auth = get_www_authenticate(rpl);
	} else if (code==PROXY_AUTH_CODE) {
		if (0 == parse_proxy_authenticate_header(rpl))
			auth = get_proxy_authenticate(rpl);
	}

	if (auth == NULL) {
		LM_ERR("Unable to extract authentication info\n");
		goto error;
	}

	/* can we authenticate this realm? */
	crd = 0;
	/* first look into AVP, if set */
	if ( auth_realm_spec.type==PVT_AVP )
		crd = get_avp_credential( msg, &auth->realm );
	/* if not found, look into predefined credentials */
	if (crd==0)
		crd = uac_auth_api._lookup_realm( &auth->realm );
	/* found? */
	if (crd==0)
	{
		LM_DBG("no credential for realm \"%.*s\"\n",
			auth->realm.len, auth->realm.s);
		goto error;
	}

	/* do authentication */
	uac_auth_api._do_uac_auth( &msg->first_line.u.request.method,
			&t->uac[branch].uri, crd, auth, &auth_nc_cnonce, response);

	/* build the authorization header */
	new_hdr = uac_auth_api._build_authorization_hdr( code, &t->uac[branch].uri,
		crd, auth, &auth_nc_cnonce, response);
	if (new_hdr==0)
	{
		LM_ERR("failed to build authorization hdr\n");
		goto error;
	}

	/* so far, so good -> add the header and set the proper RURI */
	if ( apply_urihdr_changes( msg, &t->uac[branch].uri, new_hdr)<0 )
	{
		LM_ERR("failed to apply changes\n");
		goto error;
	}

	/* increas the Cseq nr */


	return 0;
error:
	return -1;
}