1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /*
3  * soup-auth-basic.c: HTTP Basic Authentication
4  *
5  * Copyright (C) 2001-2003, Ximian, Inc.
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <string.h>
13 
14 #include "soup-auth-basic.h"
15 #include "soup.h"
16 
17 struct _SoupAuthBasic {
18 	SoupAuth parent;
19 };
20 
21 typedef struct {
22 	char *token;
23 } SoupAuthBasicPrivate;
24 
25 /**
26  * SOUP_TYPE_AUTH_BASIC:
27  *
28  * A #GType corresponding to HTTP "Basic" authentication.
29  * #SoupSessions support this by default; if you want to disable
30  * support for it, call soup_session_remove_feature_by_type(),
31  * passing %SOUP_TYPE_AUTH_BASIC.
32  *
33  */
34 
G_DEFINE_FINAL_TYPE_WITH_PRIVATE(SoupAuthBasic,soup_auth_basic,SOUP_TYPE_AUTH)35 G_DEFINE_FINAL_TYPE_WITH_PRIVATE (SoupAuthBasic, soup_auth_basic, SOUP_TYPE_AUTH)
36 
37 static void
38 soup_auth_basic_init (SoupAuthBasic *basic)
39 {
40 }
41 
42 static void
soup_auth_basic_finalize(GObject * object)43 soup_auth_basic_finalize (GObject *object)
44 {
45 	SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (object));
46 
47 	g_free (priv->token);
48 
49 	G_OBJECT_CLASS (soup_auth_basic_parent_class)->finalize (object);
50 }
51 
52 static gboolean
soup_auth_basic_update(SoupAuth * auth,SoupMessage * msg,GHashTable * auth_params)53 soup_auth_basic_update (SoupAuth *auth, SoupMessage *msg,
54 			GHashTable *auth_params)
55 {
56 	SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth));
57 
58 	/* If we're updating a pre-existing auth, the
59 	 * username/password must be bad now, so forget it.
60 	 * Other than that, there's nothing to do here.
61 	 */
62 	if (priv->token) {
63 		memset (priv->token, 0, strlen (priv->token));
64 		g_free (priv->token);
65 		priv->token = NULL;
66 	}
67 
68 	return TRUE;
69 }
70 
71 static GSList *
soup_auth_basic_get_protection_space(SoupAuth * auth,GUri * source_uri)72 soup_auth_basic_get_protection_space (SoupAuth *auth, GUri *source_uri)
73 {
74 	char *space, *p;
75 
76 	space = g_strdup (g_uri_get_path (source_uri));
77 
78 	/* Strip filename component */
79 	p = strrchr (space, '/');
80 	if (p == space && p[1])
81 		p[1] = '\0';
82 	else if (p && p[1])
83 		*p = '\0';
84 
85 	return g_slist_prepend (NULL, space);
86 }
87 
88 static void
soup_auth_basic_authenticate(SoupAuth * auth,const char * username,const char * password)89 soup_auth_basic_authenticate (SoupAuth *auth, const char *username,
90 			      const char *password)
91 {
92 	SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth));
93 	char *user_pass, *user_pass_latin1;
94 	int len;
95 
96 	user_pass = g_strdup_printf ("%s:%s", username, password);
97 	user_pass_latin1 = g_convert (user_pass, -1, "ISO-8859-1", "UTF-8",
98 				      NULL, NULL, NULL);
99 	if (user_pass_latin1) {
100 		memset (user_pass, 0, strlen (user_pass));
101 		g_free (user_pass);
102 		user_pass = user_pass_latin1;
103 	}
104 	len = strlen (user_pass);
105 
106 	if (priv->token) {
107 		memset (priv->token, 0, strlen (priv->token));
108 		g_free (priv->token);
109 	}
110 	priv->token = g_base64_encode ((guchar *)user_pass, len);
111 
112 	memset (user_pass, 0, len);
113 	g_free (user_pass);
114 }
115 
116 static gboolean
soup_auth_basic_is_authenticated(SoupAuth * auth)117 soup_auth_basic_is_authenticated (SoupAuth *auth)
118 {
119 	SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth));
120 
121 	return priv->token != NULL;
122 }
123 
124 static char *
soup_auth_basic_get_authorization(SoupAuth * auth,SoupMessage * msg)125 soup_auth_basic_get_authorization (SoupAuth *auth, SoupMessage *msg)
126 {
127 	SoupAuthBasicPrivate *priv = soup_auth_basic_get_instance_private (SOUP_AUTH_BASIC (auth));
128 
129 	return g_strdup_printf ("Basic %s", priv->token);
130 }
131 
132 static void
soup_auth_basic_class_init(SoupAuthBasicClass * auth_basic_class)133 soup_auth_basic_class_init (SoupAuthBasicClass *auth_basic_class)
134 {
135 	SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_basic_class);
136 	GObjectClass *object_class = G_OBJECT_CLASS (auth_basic_class);
137 
138 	auth_class->scheme_name = "Basic";
139 	auth_class->strength = 1;
140 
141 	auth_class->update = soup_auth_basic_update;
142 	auth_class->get_protection_space = soup_auth_basic_get_protection_space;
143 	auth_class->authenticate = soup_auth_basic_authenticate;
144 	auth_class->is_authenticated = soup_auth_basic_is_authenticated;
145 	auth_class->get_authorization = soup_auth_basic_get_authorization;
146 
147 	object_class->finalize = soup_auth_basic_finalize;
148 }
149