Exemplo n.º 1
0
static unsigned char *
get_auth_entry_text(struct listbox_item *item, struct terminal *term)
{
	struct auth_entry *auth_entry = (struct auth_entry *)item->udata;

	return get_uri_string(auth_entry->uri, URI_HTTP_AUTH);
}
Exemplo n.º 2
0
static unsigned char *
get_cache_entry_text(struct listbox_item *item, struct terminal *term)
{
	struct cache_entry *cached = item->udata;

	return get_uri_string(cached->uri, URI_PUBLIC);
}
Exemplo n.º 3
0
Arquivo: fsp.c Projeto: Efreak/elinks
static void
fsp_directory(FSP_SESSION *ses, struct uri *uri)
{
	struct string buf;
	FSP_DIR *dir;
	unsigned char *data = get_uri_string(uri, URI_DATA);
	unsigned char dircolor[8] = "";

	if (!data)
		fsp_error(connection_state(S_OUT_OF_MEM));
	decode_uri(data);
	if (!is_in_state(init_directory_listing(&buf, uri), S_OK))
		fsp_error(connection_state(S_OUT_OF_MEM));

	dir = fsp_opendir(ses, data);
	if (!dir) fsp_error(connection_state_for_errno(errno));

	fprintf(stderr, "text/html");
	fclose(stderr);

	puts(buf.source);

	if (get_opt_bool("document.browse.links.color_dirs", NULL)) {
		color_to_string(get_opt_color("document.colors.dirs", NULL),
				dircolor);
	}

	sort_and_display_entries(dir, dircolor);
	fsp_closedir(dir);
	puts("</pre><hr/></body></html>");
	fsp_close_session(ses);
	exit(0);
}
Exemplo n.º 4
0
static void
auth_ok(void *data)
{
	struct dialog *dlg = (struct dialog *)data;
	struct auth_entry *entry = (struct auth_entry *)dlg->udata2;
	struct session *ses = (struct session *)dlg->udata;

	entry->blocked = 0;
	entry->valid = auth_entry_has_userinfo(entry);

#ifdef CONFIG_FORMHIST
	if (get_opt_bool((const unsigned char *)"document.browse.forms.show_formhist", ses)) {
		unsigned char *url = get_uri_string(entry->uri, URI_HTTP_AUTH);

		if (url) {
			struct form form = {};

			form.action = url;
			INIT_LIST_OF(struct submitted_value, submit);
			struct submitted_value *user, *password;

			user = init_submitted_value((unsigned char *)"user", entry->user, FC_TEXT, NULL, 0);
			if (user) {
				add_to_list(submit, user);
			}
			password = init_submitted_value((unsigned char *)"password", entry->password, FC_PASSWORD, NULL, 0);
			if (password) {
				add_to_list(submit, password);
			}

			memorize_form(ses, &submit, &form);
			done_submitted_value_list(&submit);
			mem_free(url);
		}
	}
#endif

	if (entry->valid && have_location(ses)) {
		struct location *loc = cur_loc(ses);
		struct uri *uri = loc->vs.uri;

		/* Make a 'fake' redirect to a URI without user/password so that
		 * the user/password from the URI will not override what the
		 * user just entered in the dialog. */
		if ((uri->userlen && strlcmp(entry->user, -1, uri->user, uri->userlen))
		    || (uri->password && strlcmp(entry->password, -1, uri->password, uri->passwordlen))) {

			uri = get_composed_uri(uri, URI_HTTP_AUTH | URI_DATA | URI_POST);
			if (uri) {
				goto_uri_frame(ses, uri, NULL, CACHE_MODE_INCREMENT);
				done_uri(uri);
				return;
			}
		}
	}

	reload(ses, CACHE_MODE_INCREMENT);
}
Exemplo n.º 5
0
void
make_connection(struct socket *socket, struct uri *uri,
		socket_connect_T connect_done, int no_cache)
{
	unsigned char *host = get_uri_string(uri, URI_DNS_HOST);
	struct connect_info *connect_info;
	enum dns_result result;
	enum blacklist_flags verify;

	socket->ops->set_timeout(socket, connection_state(0));

	if (!host) {
		socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
		return;
	}

	connect_info = init_connection_info(uri, socket, connect_done);
	if (!connect_info) {
		mem_free(host);
		socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
		return;
	}

	socket->connect_info = connect_info;
	/* XXX: Keep here and not in init_connection_info() to make
	 * complete_connect_socket() work from the HTTP implementation. */
	socket->need_ssl = get_protocol_need_ssl(uri->protocol);
	if (!socket->set_no_tls) {
		enum blacklist_flags flags = get_blacklist_flags(uri);
		socket->no_tls = ((flags & SERVER_BLACKLIST_NO_TLS) != 0);
		socket->set_no_tls = 1;
	}

	verify = get_blacklist_flags(uri);
	socket->verify = ((verify & SERVER_BLACKLIST_NO_CERT_VERIFY) == 0);

	debug_transfer_log("\nCONNECTION: ", -1);
	debug_transfer_log(host, -1);
	debug_transfer_log("\n", -1);

	result = find_host(host, &connect_info->dnsquery, (dns_callback_T) dns_found,
			   socket, no_cache);

	mem_free(host);

	if (result == DNS_ASYNC)
		socket->ops->set_state(socket, connection_state(S_DNS));
}
Exemplo n.º 6
0
static unsigned char *
get_file_download_text(struct listbox_item *item, struct terminal *term)
{
	struct file_download *file_download = item->udata;
	unsigned char *uristring;

	uristring = get_uri_string(file_download->uri, URI_PUBLIC);
	if (uristring) {
#ifdef CONFIG_UTF8
		if (term->utf8_cp)
			decode_uri(uristring);
		else
#endif /* CONFIG_UTF8 */
			decode_uri_for_display(uristring);
	}

	return uristring;
}
Exemplo n.º 7
0
/* @location_class.getProperty */
static JSBool
location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
{
	JSObject *parent_win;	/* instance of @window_class */
	struct view_state *vs;

	/* This can be called if @obj if not itself an instance of the
	 * appropriate class but has one in its prototype chain.  Fail
	 * such calls.  */
	if (!JS_InstanceOf(ctx, obj, (JSClass *) &location_class, NULL))
		return JS_FALSE;
	parent_win = JS_GetParent(ctx, obj);
	assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL));
	if_assert_failed return JS_FALSE;

	vs = (struct view_state *)JS_GetInstancePrivate(ctx, parent_win,
				   (JSClass *) &window_class, NULL);

	if (!JSID_IS_INT(id))
		return JS_TRUE;

	undef_to_jsval(ctx, vp);

	switch (JSID_TO_INT(id)) {
	case JSP_LOC_HREF:
		astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL));
		break;
	default:
		/* Unrecognized integer property ID; someone is using
		 * the object as an array.  SMJS builtin classes (e.g.
		 * js_RegExpClass) just return JS_TRUE in this case
		 * and leave *@vp unchanged.  Do the same here.
		 * (Actually not quite the same, as we already used
		 * @undef_to_jsval.)  */
		break;
	}

	return JS_TRUE;
}
Exemplo n.º 8
0
static JSBool
location_get_property_href(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSMutableHandleValue hvp)
{
	ELINKS_CAST_PROP_PARAMS

	JSObject *parent_win;	/* instance of @window_class */
	struct view_state *vs;

	/* This can be called if @obj if not itself an instance of the
	 * appropriate class but has one in its prototype chain.  Fail
	 * such calls.  */
	if (!JS_InstanceOf(ctx, obj, &location_class, NULL))
		return JS_FALSE;
	parent_win = JS_GetParent(obj);
	assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
	if_assert_failed return JS_FALSE;

	vs = JS_GetInstancePrivate(ctx, parent_win,
				   &window_class, NULL);

	astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL));

	return JS_TRUE;
}
Exemplo n.º 9
0
void download_data_store( struct download *download, struct file_download *file_download )
{
  struct terminal *term = file_download->term;
  assert_terminal_ptr_not_dangling( file_download->term );
  if ( assert_failed )
  {
    assert_failed = 0;
    file_download->term = 0;
    abort_download( &file_download[0] );
    term = &term[0];
    return;
  }
  else
  {
    if ( term[0].next == 0 )
    {
      abort_download( &file_download[0] );
      term = &term[0];
      return;
    }
    else
    {
      if ( download->state.basic >= 0 )
      {
        if ( file_download->dlg_data )
        {
          redraw_dialog( file_download->dlg_data, 1 );
          return;
        }
        else
        {
          return;
        }
      }
      else
      {
        if ( file_download->dlg_data != -100000 )
        {
          unsigned char *url = get_uri_string( file_download->uri, URI_PUBLIC );
          struct connection_state state = download->state;
          state.syserr = download->state.syserr;
          abort_download_and_beep( &file_download[0], &term[0] );
          if ( url )
          {
            info_box( &term[0], MSGBOX_FREE_TEXT, "Download error", ALIGN_CENTER );
            mem_free( (void*)url );
            return;
          }
          else
          {
            return;
          }
        }
        else
        {
          if ( file_download->external_handler )
          {
            close( file_download->handle );
            file_download->handle = -1;
            exec_on_terminal( &term[0], file_download->external_handler, file_download->file, ( (int)file_download->bits_at_104/*.1_1of4*/ >> 2 ) & 1 );
            file_download->bits_at_104/*.1_1of4*/ &= 254;
            abort_download_and_beep( &file_download[0], &term[0] );
            return;
          }
          else
          {
            if ( file_download->notify )
            {
              unsigned char *url;
              url[0] = get_uri_string( file_download->uri, URI_PUBLIC );
              done_download_display( &file_download[0] );
              if ( url[0] )
              {
                info_box( &term[0], MSGBOX_FREE_TEXT, "Download", ALIGN_CENTER );
                mem_free( &url[0] );
              }
            }
            if ( file_download->remotetime && *(int*)(get_opt_( config_options, (unsigned char*)config_options )) )
            {
              struct utimbuf foo;
              foo.modtime = file_download->remotetime;
              foo.actime = file_download->remotetime;
              utime( (char*)file_download->file, &foo.actime );
            }
            abort_download_and_beep( &file_download[0], &term[0] );
            return;
          }
        }
      }
    }
Exemplo n.º 10
0
void
get_urls_css (struct map_context *ctx, int offset, int buf_length)
{
  int token;
  /*char tmp[2048];*/
  int buffer_pos = 0;
  int pos, length;
  char *uri;

  /*
  strncpy(tmp,ctx->text + offset, buf_length);
  tmp[buf_length] = '\0';
  DEBUGP (("get_urls_css: \"%s\"\n", tmp));
  */

  /* tell flex to scan from this buffer */
  yy_scan_bytes (ctx->text + offset, buf_length);

  while((token = yylex()) != CSSEOF)
    {
      /*DEBUGP (("%s ", token_names[token]));*/
      /* @import "foo.css"
         or @import url(foo.css)
      */
      if(token == IMPORT_SYM)
        {
          do {
            buffer_pos += yyleng;
          } while((token = yylex()) == S);

          /*DEBUGP (("%s ", token_names[token]));*/

          if (token == STRING || token == URI)
            {
              /*DEBUGP (("Got URI "));*/
              pos = buffer_pos + offset;
              length = yyleng;

              if (token == URI)
                {
                  uri = get_uri_string (ctx->text, &pos, &length);
                }
              else
                {
                  /* cut out quote characters */
                  pos++;
                  length -= 2;
                  uri = xmalloc (length + 1);
                  strncpy (uri, yytext + 1, length);
                  uri[length] = '\0';
                }

              if (uri)
                {
                  struct urlpos *up = append_url (uri, pos, length, ctx);
                  DEBUGP (("Found @import: [%s] at %d [%s]\n", yytext, buffer_pos, uri));

                  if (up)
                    {
                      up->link_inline_p = 1;
                      up->link_css_p = 1;
                      up->link_expect_css = 1;
                    }

                  xfree(uri);
                }
            }
        }
      /* background-image: url(foo.png)
         note that we don't care what
         property this is actually on.
      */
      else if(token == URI)
        {
          pos = buffer_pos + offset;
          length = yyleng;
          uri = get_uri_string (ctx->text, &pos, &length);

          if (uri)
            {
              struct urlpos *up = append_url (uri, pos, length, ctx);
              DEBUGP (("Found URI: [%s] at %d [%s]\n", yytext, buffer_pos, uri));
              if (up)
                {
                  up->link_inline_p = 1;
                  up->link_css_p = 1;
                }

              xfree (uri);
            }
        }
      buffer_pos += yyleng;
    }
  DEBUGP (("\n"));
}
Exemplo n.º 11
0
void
html_form(struct html_context *html_context, unsigned char *a,
          unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	unsigned char *al;
	struct form *form;

	html_context->was_br = 1;

	form = init_form();
	if (!form) return;

	form->method = FORM_METHOD_GET;
	form->form_num = a - html_context->startf;

	al = get_attr_val(a, (unsigned char *)"method", html_context->doc_cp);
	if (al) {
		if (!c_strcasecmp((const char *)al, "post")) {
			unsigned char *enctype;

			enctype  = get_attr_val(a, (unsigned char *)"enctype",
						html_context->doc_cp);

			form->method = FORM_METHOD_POST;
			if (enctype) {
				if (!c_strcasecmp((const char *)enctype, "multipart/form-data"))
					form->method = FORM_METHOD_POST_MP;
				else if (!c_strcasecmp((const char *)enctype, "text/plain"))
					form->method = FORM_METHOD_POST_TEXT_PLAIN;
				mem_free(enctype);
			}
		}
		mem_free(al);
	}
	form->onsubmit = get_attr_val(a, (unsigned char *)"onsubmit", html_context->doc_cp);
	al = get_attr_val(a, (unsigned char *)"name", html_context->doc_cp);
	if (al) form->name = al;

	al = get_attr_val(a, (unsigned char *)"action", html_context->doc_cp);
	/* The HTML specification at
	 * http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states
	 * that the behavior of an empty action attribute should be undefined.
	 * Mozilla handles action="" as action="<current-URI>" which seems
	 * reasonable. (bug 615) */
	if (al && *al) {
		form->action = join_urls(html_context->base_href, trim_chars(al, ' ', NULL));
		mem_free(al);

	} else {
		enum uri_component components = URI_ORIGINAL;

		mem_free_if(al);

		/* We have to do following for GET method, because we would end
		 * up with two '?' otherwise. */
		if (form->method == FORM_METHOD_GET)
			components = URI_FORM_GET;

		form->action = get_uri_string(html_context->base_href, components);

		/* No action URI should contain post data */
		assert(!form->action || !strchr((char *)form->action, POST_CHAR));

		/* GET method URIs should not have '?'. */
		assert(!form->action
			|| form->method != FORM_METHOD_GET
			|| !strchr((char *)form->action, '?'));
	}

	al = get_target(html_context->options, a);
	form->target = al ? al : stracpy(html_context->base_target);

	html_context->special_f(html_context, SP_FORM, form);
}
Exemplo n.º 12
0
void do_auth_dialog( struct session *ses, void *data )
{
  int edx;
  struct dialog *dlg;
  struct dialog_data *dlg_data;
  struct terminal *term = ses->tab->term;
  struct auth_entry *a;
  unsigned char sticker[1024], *text;
  int sticker_len;
  if ( get_invalid_auth_entry(  ) && !( ( *(char*)(get_invalid_auth_entry(  ) + 112) & 1 ) & 255 ) && get_uri_string( &a->uri->user[0], URI_HTTP_AUTH ) )
  {
    dlg = &a->realm[0];
    if ( 0 != 65 )
    {
      if ( term[0] && current_charset != get_terminal_codepage( &term[0] ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( &term[0] ) ) );
        *ebp_1076 = text[0];
        current_charset = get_terminal_codepage( &term[0] );
      }
      gettext( "Authentication required for %s at %s" );
      text[0] = text[0];
    }
    sticker_len = __snprintf_chk( sticker, 1024, 1, 1024, (char*)gettext( "Authentication required for %s at %s" ), dlg, text[0] );
    mem_free( &text[0] );
    if ( sticker_len <= 1024 )
    {
      dlg = (struct dialog*)mem_calloc( 1, sticker_len + 277 );
      if ( dlg )
      {
        a->bits_at_112/*.1_1of4*/ |= 1;
        dlg->layouter = &generic_dialog_layouter;
        dlg[0].title = _( "Authentication required", &term[0] );
        text[0] = dlg[3].abort;
        memcpy( dlg[3].abort, sticker, sticker_len );
        dlg->udata = (void*)ses[0].next;
        dlg->udata2 = (void*)a[0].next;
        add_dlg_text( dlg, (unsigned char*)dlg[3].abort, ALIGN_LEFT, 0 );
        add_dlg_field_do( dlg, WIDGET_FIELD, _( "Login", &term[0] ), 0, 0, 0, 40, &a->user[0], 0, INPFIELD_FLOAT );
        add_dlg_field_do( dlg, WIDGET_FIELD_PASS, _( "Password", &term[0] ), 0, 0, 0, 40, &a->password[0], 0, INPFIELD_FLOAT );
        add_dlg_button_do( dlg, _( "~OK", &term[0] ), 1, &ok_dialog, 0, &auth_ok, (void*)dlg );
        add_dlg_button_do( dlg, _( "~Cancel", &term[0] ), 2, &ok_dialog, 0, &auth_cancel, (void*)a[0].next );
        if ( assert_failed == 0 )
        {
          assert_failed = dlg->number_of_widgets != 5;
          if ( dlg->number_of_widgets != 5 )
          {
            errfile = "/home/naftali/source/elinks-0.12~pre5/src/protocol/auth/dialogs.c";
            errline = 118;
            elinks_internal( "assertion 5 == (dlg)-&gt;number_of_widgets failed!" );
          }
        }
        if ( dlg_data[0] && a->user[0] && a->password[0] == 0 )
          select_widget_by_id( &dlg_data[0], 1 );
      }
    }
  }
  if ( 0 ^ 0 )
  {
    __stack_chk_fail(  );
  }
  return;
}
Exemplo n.º 13
0
void
mailcap_protocol_handler(struct connection *conn)
{
#ifdef HAVE_FORK
	unsigned char *script, *ref;
	pid_t pid;
	struct connection_state state = connection_state(S_OK);
	int pipe_read[2], check;

	/* security checks */
	if (!conn->referrer || conn->referrer->protocol != PROTOCOL_MAILCAP) {
		goto bad;
	}
	ref = get_uri_string(conn->referrer, URI_DATA);
	if (!ref) {
		goto bad;
	}
	check = strcmp(ref, "elmailcap");
	mem_free(ref);
	if (check) goto bad;
	
	script = get_uri_string(conn->uri, URI_DATA);
	if (!script) {
		state = connection_state(S_OUT_OF_MEM);
		goto end2;
	}

	if (c_pipe(pipe_read)) {
		state = connection_state_for_errno(errno);
		goto end1;
	}

	pid = fork();
	if (pid < 0) {
		state = connection_state_for_errno(errno);
		goto end0;
	}
	if (!pid) {
		if (dup2(pipe_read[1], STDOUT_FILENO) < 0) {
			_exit(2);
		}
		/* We implicitly chain stderr to ELinks' stderr. */
		close_all_non_term_fd();

		if (execl("/bin/sh", "/bin/sh", "-c", script, (char *) NULL)) {
			_exit(3);
		}

	} else { /* ELinks */
		mem_free(script);

		if (!init_http_connection_info(conn, 1, 0, 1)) {
			close(pipe_read[0]); close(pipe_read[1]);
			return;
		}

		close(pipe_read[1]);
		conn->socket->fd = pipe_read[0];

		conn->data_socket->fd = -1;
		conn->cgi = 1;
		set_nonblocking_fd(conn->socket->fd);

		get_request(conn);
		return;
	}

end0:
	close(pipe_read[0]); close(pipe_read[1]);
end1:
	mem_free(script);
end2:
	abort_connection(conn, state);
	return;
#endif
bad:
	abort_connection(conn, connection_state(S_BAD_URL));
}
Exemplo n.º 14
0
Arquivo: smb2.c Projeto: Efreak/elinks
static void
do_smb(struct connection *conn)
{
	struct uri *uri = conn->uri;
	struct auth_entry *auth = find_auth(uri);
	struct string string;
	unsigned char *url;
	int dir;

	if ((uri->userlen && uri->passwordlen) || !auth) {
		url = get_uri_string(uri, URI_BASE);
	} else {
		unsigned char *uri_string = get_uri_string(uri, URI_HOST | URI_PORT | URI_DATA);

		if (!uri_string || !init_string(&string)) {
			smb_error(connection_state(S_OUT_OF_MEM));
		}
		/* Must URI-encode the username and password to avoid
		 * ambiguity if they contain "/:@" characters.
		 * Libsmbclient then decodes them again, and the
		 * server gets them as they were in auth->user and
		 * auth->password, i.e. as the user typed them in the
		 * auth dialog.  This implies that, if the username or
		 * password contains some characters or bytes that the
		 * user cannot directly type, then she cannot enter
		 * them.  If that becomes an actual problem, it should
		 * be fixed in the auth dialog, e.g. by providing a
		 * hexadecimal input mode.  */
		add_to_string(&string, "smb://");
		encode_uri_string(&string, auth->user, -1, 1);
		add_char_to_string(&string, ':');
		encode_uri_string(&string, auth->password, -1, 1);
		add_char_to_string(&string, '@');
		add_to_string(&string, uri_string);
		url = string.source;
	}

	if (!url) {
		smb_error(connection_state(S_OUT_OF_MEM));
	}
	if (smbc_init(smb_auth, 0)) {
		smb_error(connection_state_for_errno(errno));
	};


	dir = smbc_opendir(url);
	if (dir >= 0) {
		struct string prefix;

		init_string(&prefix);
		add_to_string(&prefix, url);
		add_char_to_string(&prefix, '/');
		smb_directory(dir, &prefix, conn->uri);
		done_string(&prefix);
	} else {
		const int errno_from_opendir = errno;
		char buf[READ_SIZE];
		struct stat sb;
		int r, res, fdout;
		int file = smbc_open(url, O_RDONLY, 0);

		if (file < 0) {
			/* If we're opening the list of shares without
			 * proper authentication, then smbc_opendir
			 * fails with EACCES and smbc_open fails with
			 * ENOENT.  In this case, return the EACCES so
			 * that the parent ELinks process will prompt
			 * for credentials.  */
			if (errno == ENOENT && errno_from_opendir == EACCES)
				errno = errno_from_opendir;
			smb_error(connection_state_for_errno(errno));
		}

		res = smbc_fstat(file, &sb);
		if (res) {
			smb_error(connection_state_for_errno(res));
		}
		/* filesize */
		fprintf(header_out, "%" OFF_PRINT_FORMAT,
			(off_print_T) sb.st_size);
		fclose(header_out);

		fdout = fileno(data_out);
		while ((r = smbc_read(file, buf, READ_SIZE)) > 0) {
			if (safe_write(fdout, buf, r) <= 0)
					break;
		}
		smbc_close(file);
		exit(0);
	}
}
Exemplo n.º 15
0
Arquivo: task.c Projeto: ezc/elinks
void
ses_goto(struct session *ses, struct uri *uri, unsigned char *target_frame,
	 struct location *target_location, enum cache_mode cache_mode,
	 enum task_type task_type, int redir)
{
	/* [gettext_accelerator_context(ses_goto)] */
	struct task *task;
	int referrer_incomplete = 0;
	int malicious_uri = 0;
	int confirm_submit = uri->form && get_opt_bool("document.browse.forms"
	                                               ".confirm_submit", ses);
	unsigned char *m1 = NULL, *message = NULL;
	struct memory_list *mlist = NULL;

	if (ses->doc_view
	    && ses->doc_view->document
	    && ses->doc_view->document->refresh) {
		kill_document_refresh(ses->doc_view->document->refresh);
	}

	assertm(!ses->loading_uri, "Buggy URI reference counting");

	/* Reset the redirect counter if this is not a redirect. */
	if (!redir) {
		ses->redirect_cnt = 0;
	}

	/* Figure out whether to confirm submit or not */

	/* Only confirm submit if we are posting form data or a misleading URI
	 * was detected. */
	/* Note uri->post might be empty here but we are still supposely
	 * posting form data so this should be more correct. */

	if (uri->user && uri->userlen
	    && get_opt_bool("document.browse.links.warn_malicious", ses)
	    && check_malicious_uri(uri)) {
		malicious_uri = 1;
		confirm_submit = 1;

	} else if (uri->form) {
		/* First check if the referring URI was incomplete. It
		 * indicates that the posted form data might be incomplete too.
		 * See bug 460. */
		if (ses->referrer) {
			struct cache_entry *cached;

			cached = find_in_cache(ses->referrer);
			referrer_incomplete = (cached && cached->incomplete);
		}

		if (referrer_incomplete) {
			confirm_submit = 1;

		} else if (get_validated_cache_entry(uri, cache_mode)) {
			confirm_submit = 0;
		}
	}

	if (!confirm_submit) {
		ses_load(ses, get_uri_reference(uri), target_frame,
		         target_location, cache_mode, task_type);
		return;
	}

	task = mem_alloc(sizeof(*task));
	if (!task) return;

	task->ses = ses;
	task->uri = get_uri_reference(uri);
	task->cache_mode = cache_mode;
	task->session_task.type = task_type;
	task->session_task.target.frame = null_or_stracpy(target_frame);
	task->session_task.target.location = target_location;

	if (malicious_uri) {
		unsigned char *host = memacpy(uri->host, uri->hostlen);
		unsigned char *user = memacpy(uri->user, uri->userlen);
		unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);

		message = msg_text(ses->tab->term,
			N_("The URL you are about to follow might be maliciously "
			"crafted in order to confuse you. By following the URL "
			"you will be connecting to host \"%s\" as user \"%s\".\n\n"
			"Do you want to go to URL %s?"), host, user, uristring);

		mem_free_if(host);
		mem_free_if(user);
		mem_free_if(uristring);

	} else if (redir) {
		m1 = N_("Do you want to follow the redirect and post form data "
			"to URL %s?");

	} else if (referrer_incomplete) {
		m1 = N_("The form data you are about to post might be incomplete.\n"
			"Do you want to post to URL %s?");

	} else if (task_type == TASK_FORWARD) {
		m1 = N_("Do you want to post form data to URL %s?");

	} else {
		m1 = N_("Do you want to repost form data to URL %s?");
	}

	if (!message && m1) {
		unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);

		message = msg_text(ses->tab->term, m1, uristring);
		mem_free_if(uristring);
	}

	add_to_ml(&mlist, task, (void *) NULL);
	if (task->session_task.target.frame)
		add_to_ml(&mlist, task->session_task.target.frame, (void *) NULL);
	msg_box(ses->tab->term, mlist, MSGBOX_FREE_TEXT,
		N_("Warning"), ALIGN_CENTER,
		message,
		task, 2,
		MSG_BOX_BUTTON(N_("~Yes"), post_yes, B_ENTER),
		MSG_BOX_BUTTON(N_("~No"), post_no, B_ESC));
}
Exemplo n.º 16
0
/* Return -1 on error, 0 or success. */
int
ssl_connect(struct socket *socket)
{
	int ret;
	unsigned char *server_name;
	struct connection *conn = (struct connection *)socket->conn;

	/* TODO: Recode server_name to UTF-8.  */
	server_name = get_uri_string(conn->proxied_uri, URI_HOST);
	if (!server_name) {
		socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
		return -1;
	}

	/* RFC 3546 says literal IPv4 and IPv6 addresses are not allowed.  */
	if (is_ip_address(server_name, strlen((const char *)server_name)))
		mem_free_set(&server_name, NULL);

	if (init_ssl_connection(socket, server_name) == S_SSL_ERROR) {
		mem_free_if(server_name);
		socket->ops->done(socket, connection_state(S_SSL_ERROR));
		return -1;
	}

	mem_free_if(server_name);

	if (socket->no_tls)
		ssl_set_no_tls(socket);

#ifdef USE_OPENSSL
	SSL_set_fd((SSL *)socket->ssl, socket->fd);

	if (get_opt_bool((const unsigned char *)"connection.ssl.cert_verify", NULL))
		SSL_set_verify((SSL *)socket->ssl, SSL_VERIFY_PEER
					  | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
			       verify_callback);

	if (get_opt_bool((const unsigned char *)"connection.ssl.client_cert.enable", NULL)) {
		unsigned char *client_cert;

#ifdef CONFIG_NSS_COMPAT_OSSL
		client_cert = get_opt_str(
				(const unsigned char *)"connection.ssl.client_cert.nickname", NULL);
#else
		client_cert = get_opt_str(
				(const unsigned char *)"connection.ssl.client_cert.file", NULL);
#endif
		if (!*client_cert) {
			client_cert = (unsigned char *)getenv("X509_CLIENT_CERT");
			if (client_cert && !*client_cert)
				client_cert = NULL;
		}

		if (client_cert) {
#ifdef CONFIG_NSS_COMPAT_OSSL
			SSL_CTX_use_certificate_chain_file(
					(SSL *) socket->ssl,
					(const char *)client_cert);
#else
			SSL_CTX *ctx = ((SSL *) socket->ssl)->ctx;

			SSL_CTX_use_certificate_chain_file(ctx, (const char *)client_cert);
			SSL_CTX_use_PrivateKey_file(ctx, (const char *)client_cert,
						    SSL_FILETYPE_PEM);
#endif
		}
	}

#elif defined(CONFIG_GNUTLS)
	/* GnuTLS uses function pointers for network I/O.  The default
	 * functions take a file descriptor, but it must be passed in
	 * as a pointer.  GnuTLS uses the GNUTLS_INT_TO_POINTER and
	 * GNUTLS_POINTER_TO_INT macros for these conversions, but
	 * those are unfortunately not in any public header.  So
	 * ELinks must just cast the pointer the best it can and hope
	 * that the conversions match.  */
	gnutls_transport_set_ptr(*((ssl_t *) socket->ssl),
				 (gnutls_transport_ptr_t) (longptr_T) socket->fd);

	/* TODO: Some certificates fuss. --pasky */
#endif

	ret = ssl_do_connect(socket);

	switch (ret) {
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_READ2:
			socket->ops->set_state(socket, connection_state(S_SSL_NEG));
			set_handlers(socket->fd, (select_handler_T) ssl_want_read,
				     NULL, (select_handler_T) dns_exception, socket);
			return -1;

		case SSL_ERROR_NONE:
#ifdef CONFIG_GNUTLS
			if (!get_opt_bool((const unsigned char *)"connection.ssl.cert_verify", NULL))
				break;

			if (!verify_certificates(socket))
#endif
				break;

		default:
			if (ret != SSL_ERROR_NONE) {
				/* DBG("sslerr %s", gnutls_strerror(ret)); */
				socket->no_tls = !socket->no_tls;
			}

			connect_socket(socket, connection_state(S_SSL_ERROR));
			return -1;
	}

	return 0;
}
Exemplo n.º 17
0
/** Verify one certificate in the server certificate chain.
 * This callback is documented in SSL_set_verify(3).  */
static int
verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
	X509 *cert;
	SSL *ssl;
	struct socket *socket;
	struct connection *conn;
	unsigned char *host_in_uri;
	GENERAL_NAMES *alts;
	int saw_dns_name = 0;
	int matched = 0;

	/* If OpenSSL already found a problem, keep that.  */
	if (!preverify_ok)
		return 0;

	/* Examine only the server certificate, not CA certificates.  */
	if (X509_STORE_CTX_get_error_depth(ctx) != 0)
		return preverify_ok;

	cert = X509_STORE_CTX_get_current_cert(ctx);
	ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
	socket = (struct socket *)SSL_get_ex_data(ssl, socket_SSL_ex_data_idx);
	conn = (struct connection *)socket->conn;
	host_in_uri = get_uri_string(conn->uri, URI_HOST | URI_IDN);
	if (!host_in_uri)
		return 0;

	/* RFC 5280 section 4.2.1.6 describes the subjectAltName extension.
	 * RFC 2818 section 3.1 says Common Name must not be used
	 * if dNSName is present.  */
	alts = (GENERAL_NAMES *)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
	if (alts != NULL) {
		int alt_count;
		int alt_pos;
		GENERAL_NAME *alt;

		alt_count = sk_GENERAL_NAME_num(alts);
		for (alt_pos = 0; !matched && alt_pos < alt_count; ++alt_pos) {
			alt = sk_GENERAL_NAME_value(alts, alt_pos);
			if (alt->type == GEN_DNS) {
				saw_dns_name = 1;
				matched = match_uri_host_name(host_in_uri,
							      alt->d.dNSName);
			} else if (alt->type == GEN_IPADD) {
				matched = match_uri_host_ip(host_in_uri,
							    alt->d.iPAddress);
			}
		}

		/* Free the GENERAL_NAMES list and each element.  */
		sk_GENERAL_NAME_pop_free(alts, GENERAL_NAME_free);
	}

	if (!matched && !saw_dns_name) {
		X509_NAME *name;
		int cn_index;
		X509_NAME_ENTRY *entry = NULL;

		name = X509_get_subject_name(cert);
		cn_index = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
		if (cn_index >= 0)
			entry = X509_NAME_get_entry(name, cn_index);
		if (entry != NULL)
			matched = match_uri_host_name(host_in_uri,
						      X509_NAME_ENTRY_get_data(entry));
	}

	mem_free(host_in_uri);
	return matched;
}
Exemplo n.º 18
0
static int
verify_certificates(struct socket *socket)
{
	gnutls_x509_crt_t cert;
	gnutls_session_t session = *(ssl_t *)socket->ssl;
	struct connection *conn = socket->conn;
	const gnutls_datum_t *cert_list;
	unsigned char *hostname;
	int ret;
	unsigned int cert_list_size, status;


	ret = gnutls_certificate_verify_peers2(session, &status);
	if (ret) return ret;
	if (status) return status;

	/* If the certificate is of a type for which verification has
	 * not yet been implemented, then reject it.  This way, a fake
	 * server cannot avoid verification by using a strange type of
	 * certificate.
	 *
	 * OpenPGP certificates shouldn't even get this far anyway,
	 * because init_ssl_connection() tells GnuTLS to disable
	 * OpenPGP, and ELinks never calls
	 * gnutls_certificate_set_openpgp_keyring_file, so status
	 * should have been GNUTLS_CERT_SIGNER_NOT_FOUND.  */
	if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
		return -7;

	if (gnutls_x509_crt_init(&cert) < 0) {
		return -1;
	}

	cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
	if (!cert_list) {
		return -2;
	}

	if (gnutls_x509_crt_import(cert, &cert_list[0],
		GNUTLS_X509_FMT_DER) < 0) {
		return -3;
	}
	if (gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) {
		gnutls_x509_crt_deinit(cert);
		return -4;
	}

	if (gnutls_x509_crt_get_activation_time(cert) > time(NULL)) {
		gnutls_x509_crt_deinit(cert);
		return -5;
	}

	/* Because RFC 5280 defines dNSName as an IA5String, it can
	 * only contain ASCII characters.  Internationalized domain
	 * names must thus be in Punycode form.  Because GnuTLS 2.8.6
	 * does not itself support IDN, ELinks must convert.  */
	hostname = get_uri_string(conn->uri, URI_HOST | URI_IDN);
	if (!hostname) return -6;

	ret = !gnutls_x509_crt_check_hostname(cert, hostname);
	gnutls_x509_crt_deinit(cert);
	mem_free(hostname);
	return ret;
}
Exemplo n.º 19
0
Arquivo: fsp.c Projeto: Efreak/elinks
static void
do_fsp(struct connection *conn)
{
	FSP_SESSION *ses;
	struct stat sb;
	struct uri *uri = conn->uri;
	struct auth_entry *auth;
	unsigned char *host = get_uri_string(uri, URI_HOST);
	unsigned char *data = get_uri_string(uri, URI_DATA);
	unsigned short port = (unsigned short)get_uri_port(uri);
	unsigned char *password = NULL;

	decode_uri(data);
	if (uri->passwordlen) {
		password = get_uri_string(uri, URI_PASSWORD);
	} else {
		auth = find_auth(uri);
		if (auth) password = auth->password;
	}

	/* fsp_open_session may not set errno if getaddrinfo fails
	 * https://sourceforge.net/tracker/index.php?func=detail&aid=2036798&group_id=93841&atid=605738
	 * Try to detect this bug and use an ELinks-specific error
	 * code instead, so that we can display a message anyway.  */
	errno = 0;
	ses = fsp_open_session(host, port, password);
	if (!ses) {
		if (errno)
			fsp_error(connection_state_for_errno(errno));
		else
			fsp_error(connection_state(S_FSP_OPEN_SESSION_UNKN));
	}

	/* fsplib 0.8 ABI depends on _FILE_OFFSET_BITS
	 * https://sourceforge.net/tracker/index.php?func=detail&aid=1674729&group_id=93841&atid=605738
	 * If ELinks and fsplib are using different values of
	 * _FILE_OFFSET_BITS, then they get different definitions of
	 * struct stat, and the st_size stored by fsp_stat is
	 * typically not the same as the st_size read by ELinks.
	 * Fortunately, st_mode seems to have the same offset and size
	 * in both versions of struct stat.
	 *
	 * If all the bytes used by the 32-bit st_size are also used
	 * by the 64-bit st_size, then ELinks may be able to guess
	 * which ones they are, because the current version 2 of FSP
	 * supports only 32-bit file sizes in protocol packets.  Begin
	 * by filling struct stat with 0xAA so that it's easier to
	 * detect which bytes fsp_stat has left unchanged.  (Only
	 * sb.st_size really needs to be filled, but filling the rest
	 * too helps viewing the data with a debugger.)  */
	memset(&sb, 0xAA, sizeof(sb));
	if (fsp_stat(ses, data, &sb)) fsp_error(connection_state_for_errno(errno));

	if (S_ISDIR(sb.st_mode)) {
		fsp_directory(ses, uri);
	} else { /* regular file */
		char buf[READ_SIZE];
		FSP_FILE *file = fsp_fopen(ses, data, "r");
		int r;

		if (!file) {
			fsp_error(connection_state_for_errno(errno));
		}

#if SIZEOF_OFF_T >= 8
		if (sb.st_size < 0 || sb.st_size > 0xFFFFFFFF) {
			/* Probably a _FILE_OFFSET_BITS mismatch as
			 * described above.  Try to detect which half
			 * of st_size is the real size.  This may
			 * depend on the endianness of the processor
			 * and on the padding in struct stat.  */
			if ((sb.st_size & 0xFFFFFFFF00000000ULL) == 0xAAAAAAAA00000000ULL)
				sb.st_size = sb.st_size & 0xFFFFFFFF;
			else if ((sb.st_size & 0xFFFFFFFF) == 0xAAAAAAAA)
				sb.st_size = (sb.st_size >> 32) & 0xFFFFFFFF;
			else	/* Can't figure it out. */
				sb.st_size = 1;
		}
#endif

		/* Send filesize */
		fprintf(stderr, "%" OFF_PRINT_FORMAT "\n",
			(off_print_T) sb.st_size);
		fclose(stderr);

		while ((r = fsp_fread(buf, 1, READ_SIZE, file)) > 0) {
			int off = 0;

			while (r) {
				int w = safe_write(STDOUT_FILENO, buf + off, r);

				if (w == -1) goto out;
				off += w;
				r -= w;
			}
		}
out:
		fsp_fclose(file);
		fsp_close_session(ses);
		exit(0);
	}
Exemplo n.º 20
0
static void
download_dialog_layouter(struct dialog_data *dlg_data)
{
	struct file_download *file_download = dlg_data->dlg->udata;
	struct terminal *term = dlg_data->win->term;
	int w = dialog_max_width(term);
	int rw = w;
	int x, y = 0;
	int url_len;
	unsigned char *url;
	struct download *download = &file_download->download;
	struct color_pair *dialog_text_color = get_bfu_color(term, "dialog.text");
	unsigned char *msg = get_download_msg(download, term, 1, 1, "\n");
	int show_meter = (download_is_progressing(download)
			  && download->progress->size >= 0);
#if CONFIG_BITTORRENT
	int bittorrent = (file_download->uri->protocol == PROTOCOL_BITTORRENT
			  && (show_meter || is_in_state(download->state, S_RESUME)));
#endif

	redraw_windows(REDRAW_BEHIND_WINDOW, dlg_data->win);
	file_download->dlg_data = dlg_data;

	if (!msg) return;

	url = get_uri_string(file_download->uri, URI_PUBLIC);
	if (!url) {
		mem_free(msg);
		return;
	}
#ifdef CONFIG_UTF8
	if (term->utf8_cp)
		decode_uri(url);
	else
#endif /* CONFIG_UTF8 */
		decode_uri_for_display(url);
	url_len = strlen(url);

	if (show_meter) {
		int_lower_bound(&w, DOWN_DLG_MIN);
	}

	dlg_format_text_do(dlg_data, url, 0, &y, w, &rw,
			dialog_text_color, ALIGN_LEFT, 1);

	y++;
	if (show_meter) y += 2;

#if CONFIG_BITTORRENT
	if (bittorrent) y += 2;
#endif
	dlg_format_text_do(dlg_data, msg, 0, &y, w, &rw,
			dialog_text_color, ALIGN_LEFT, 1);

	y++;
	dlg_format_buttons(dlg_data, dlg_data->widgets_data,
			   dlg_data->number_of_widgets, 0, &y, w,
			   &rw, ALIGN_CENTER, 1);

	draw_dialog(dlg_data, w, y);

	w = rw;
	if (url_len > w) {
		/* Truncate too long urls */
		url_len = w;
		url[url_len] = '\0';
		if (url_len > 4) {
			url[--url_len] = '.';
			url[--url_len] = '.';
			url[--url_len] = '.';
		}
	}

	y = dlg_data->box.y + DIALOG_TB + 1;
	x = dlg_data->box.x + DIALOG_LB;
	dlg_format_text_do(dlg_data, url, x, &y, w, NULL,
			dialog_text_color, ALIGN_LEFT, 0);

	if (show_meter) {
		y++;
		draw_progress_bar(download->progress, term, x, y, w, NULL, NULL);
		y++;
	}

#if CONFIG_BITTORRENT
	if (bittorrent) {
		y++;
		draw_bittorrent_piece_progress(download, term, x, y, w, NULL, NULL);
		y++;
	}
#endif
	y++;
	dlg_format_text_do(dlg_data, msg, x, &y, w, NULL,
			dialog_text_color, ALIGN_LEFT, 0);

	y++;
	dlg_format_buttons(dlg_data, dlg_data->widgets_data,
			   dlg_data->number_of_widgets, x, &y, w,
			   NULL, ALIGN_CENTER, 0);

	mem_free(url);
	mem_free(msg);
}
Exemplo n.º 21
0
/* TODO: Take auth_entry from data. --jonas */
void
do_auth_dialog(struct session *ses, void *data)
{
	/* [gettext_accelerator_context(do_auth_dialog)] */
	struct dialog *dlg;
	struct dialog_data *dlg_data;
	struct terminal *term = ses->tab->term;
	struct auth_entry *a = get_invalid_auth_entry();
	unsigned char sticker[MAX_STR_LEN], *text;
	int sticker_len;

	if (!a || a->blocked) return;

	text = get_uri_string(a->uri, URI_HTTP_AUTH);
	if (!text) return;

#ifdef CONFIG_FORMHIST
	{
		unsigned char *user = get_form_history_value(text, (unsigned char *)"user");
		unsigned char *password = get_form_history_value(text, (unsigned char *)"password");

		if (user) {
			strncpy((char *)a->user, (const char *)user, AUTH_USER_MAXLEN - 1);
		}
		if (password) {
			strncpy((char *)a->password, (const char *)password, AUTH_PASSWORD_MAXLEN - 1);
		}
	}
#endif

	sticker_len = snprintf((char *)sticker, sizeof(sticker),
			       (const char *)_("Authentication required for %s at %s", term),
			       a->realm, text);
	mem_free(text);
	if (sticker_len < 0 || sticker_len > MAX_STR_LEN) return;

#define AUTH_WIDGETS_COUNT 5
	/* + 1 to leave room for the '\0'. */
	dlg = calloc_dialog(AUTH_WIDGETS_COUNT, sticker_len + 1);
	if (!dlg) return;

	a->blocked = 1;

	/* This function is used for at least HTTP and FTP, so don't
	 * name the protocol here.  Consider also what an FTP server
	 * behind an HTTP proxy should be called.  */
	dlg->title = _("Authentication required", term);
	dlg->layouter = generic_dialog_layouter;

	text = get_dialog_offset(dlg, AUTH_WIDGETS_COUNT);
	memcpy(text, sticker, sticker_len); /* calloc_dialog has stored '\0' */

	dlg->udata = (void *) ses;
	dlg->udata2 = a;

	add_dlg_text(dlg, text, ALIGN_LEFT, 0);
	add_dlg_field_float(dlg, _("Login", term), 0, 0, NULL, AUTH_USER_MAXLEN, a->user, NULL);
	add_dlg_field_float_pass(dlg, _("Password", term), 0, 0, NULL, AUTH_PASSWORD_MAXLEN, a->password);

	add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, auth_ok, dlg);
	add_dlg_ok_button(dlg, _("~Cancel", term), B_ESC, auth_cancel, a);

	add_dlg_end(dlg, AUTH_WIDGETS_COUNT);

	dlg_data = do_dialog(term, dlg, getml(dlg, (void *) NULL));
	/* When there's some username, but no password, automagically jump to
	 * the password. */
	if (dlg_data && a->user[0] && !a->password[0])
		select_widget_by_id(dlg_data, 1);
}