66#include <account.h>
77#include <signal.h>
88#include <core.h>
9+ #include <debug.h>
910
1011#include <glib.h>
1112#include <string.h>
1415#include <wincred.h>
1516
1617#define MAX_READ_LEN 2048
18+ #define PLUGIN_ID "core-wincred"
19+
1720
1821/* function prototypes */
19- static void keyring_password_store (PurpleAccount * account , char * password );
22+ static void keyring_password_store (PurpleAccount * account );
2023static BOOL keyring_password_get (PurpleAccount * account );
21- static gunichar2 * create_account_str (PurpleAccount * account );
24+ static gchar * create_account_str (PurpleAccount * account );
2225static void sign_in_cb (PurpleAccount * account , gpointer data );
2326static void connecting_cb (PurpleAccount * account , gpointer data );
2427static PurplePluginPrefFrame * get_pref_frame (PurplePlugin * plugin );
@@ -54,13 +57,8 @@ static gboolean plugin_load(PurplePlugin *plugin) {
5457 /* if the password was saved by libpurple before then
5558 * save it in the keyring, and tell libpurple to forget it */
5659 if (purple_account_get_remember_password (account )) {
57- gchar * password = g_strdup (account -> password );
58- keyring_password_store (account , password );
60+ keyring_password_store (account );
5961 purple_account_set_remember_password (account , FALSE);
60- /* temporarily set a fake password, then the real one again */
61- purple_account_set_password (account , "fakedoopdeedoop" );
62- purple_account_set_password (account , password );
63- g_free (password );
6462 }
6563 }
6664 /* done with the notFound, so free it */
@@ -80,7 +78,7 @@ static gboolean plugin_load(PurplePlugin *plugin) {
8078
8179/* callback to whenever an account is signed in */
8280static void sign_in_cb (PurpleAccount * account , gpointer data ) {
83- keyring_password_store (account , account -> password );
81+ keyring_password_store (account );
8482 return ;
8583}
8684
@@ -96,45 +94,61 @@ static void connecting_cb(PurpleAccount *account, gpointer data) {
9694/* Creats a newly allocated account string to name the windows
9795 * credential. The string returned must later be freed with g_free()
9896 */
99- static gunichar2 * create_account_str (PurpleAccount * account ) {
97+ static gchar * create_account_str (PurpleAccount * account ) {
10098 gchar * account_str = g_strdup_printf ("libpurple/%s/%s" ,
10199 account -> protocol_id , account -> username );
102- gunichar2 * uaccount_str = g_utf8_to_utf16 (account_str ,
103- strlen (account_str ), NULL , NULL , NULL );
104- g_free (account_str );
105- return uaccount_str ;
100+ return (account_str );
106101}
107102
108103/* store a password in the keyring */
109- static void keyring_password_store (PurpleAccount * account ,
110- char * password ) {
104+ static void keyring_password_store (PurpleAccount * account ) {
105+ char * password = account -> password ;
111106 int length = strlen (password );
112- /* unicode encoding of the password */
113- gunichar2 * upass = g_utf8_to_utf16 (password , length , NULL , NULL , NULL );
114- gunichar2 * account_str = create_account_str (account );
107+ gchar * account_str = create_account_str (account );
108+ /* unicode encodings of the password and account string */
109+ gunichar2 * unicode_password = g_utf8_to_utf16 (password , length ,
110+ NULL , NULL , NULL );
111+ gunichar2 * unicode_account_str = g_utf8_to_utf16 (account_str ,
112+ strlen (account_str ), NULL , NULL , NULL );
115113 /* make the credential */
116114 CREDENTIALW cred = {0 };
117115 cred .Type = CRED_TYPE_GENERIC ;
118116 cred .Persist = CRED_PERSIST_LOCAL_MACHINE ;
119- cred .TargetName = account_str ;
120- cred .UserName = account_str ;
121- cred .CredentialBlob = (BYTE * ) upass ;
117+ cred .TargetName = unicode_account_str ;
118+ cred .UserName = unicode_account_str ;
119+ cred .CredentialBlob = (BYTE * ) unicode_password ;
122120 cred .CredentialBlobSize = sizeof (BYTE ) * sizeof (gunichar2 ) * length ;
123121 /* write the credential, then free memory */
124122 CredWriteW (& cred , 0 );
125123 g_free (account_str );
126- g_free (upass );
124+ g_free (unicode_password );
125+ g_free (unicode_account_str );
127126}
128127
129128/* retrive a password from the keyring */
130129static BOOL keyring_password_get (PurpleAccount * account ) {
131- gunichar2 * account_str = create_account_str (account );
130+ gchar * account_str = create_account_str (account );
131+ gunichar2 * unicode_account_str = g_utf8_to_utf16 (account_str ,
132+ strlen (account_str ), NULL , NULL , NULL );
132133 PCREDENTIALW cred ;
133- BOOL result = CredReadW (account_str , CRED_TYPE_GENERIC , 0 , & cred );
134+ BOOL result = CredReadW (unicode_account_str , CRED_TYPE_GENERIC , 0 , & cred );
134135 /* if the password exists in the keyring, set it in pidgin */
135136 if (result ) {
137+ /* decode the password from unicode */
136138 gchar * password = g_utf16_to_utf8 ((gunichar2 * )cred -> CredentialBlob ,
137139 MAX_READ_LEN , NULL , NULL , NULL );
140+ /* process the password in case account_str was appended to
141+ * the end, as observed in some cases */
142+ char * appended = strstr (password , account_str );
143+ if (appended != NULL ) {
144+ int actual_length = appended - password ;
145+ gchar * fixed_password = g_strndup (password , actual_length );
146+ g_free (password );
147+ password = fixed_password ;
148+ purple_debug_warning (PLUGIN_ID ,
149+ "account_string %s detected at the end of the password\n" ,
150+ account_str );
151+ }
138152 purple_account_set_password (account , password );
139153 /* set the account to not remember passwords */
140154 purple_account_set_remember_password (account , FALSE);
@@ -144,6 +158,7 @@ static BOOL keyring_password_get(PurpleAccount *account) {
144158 g_free (password );
145159 }
146160 g_free (account_str );
161+ g_free (unicode_account_str );
147162 CredFree (cred );
148163 return result ;
149164}
@@ -186,10 +201,10 @@ static PurplePluginInfo info = {
186201 NULL ,
187202 PURPLE_PRIORITY_HIGHEST ,
188203
189- "core-wincred" ,
204+ PLUGIN_ID ,
190205 "Windows Credentials" ,
191206 /* version */
192- "0.3 " ,
207+ "0.4 " ,
193208
194209 "Save passwords as windows credentials instead of as plaintext" ,
195210 "Save passwords as windows credentials instead of as plaintext" ,
0 commit comments