]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/netrc.cc
* apt-pkg/sourcelist.cc:
[apt.git] / apt-pkg / contrib / netrc.cc
CommitLineData
592b7800
MV
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: netrc.c,v 1.38 2007-11-07 09:21:35 bagder Exp $
4/* ######################################################################
5
6 netrc file parser - returns the login and password of a give host in
7 a specified netrc-type file
8
9 Originally written by Daniel Stenberg, <daniel@haxx.se>, et al. and
10 placed into the Public Domain, do with it what you will.
11
12 ##################################################################### */
13 /*}}}*/
ea542140 14#include <config.h>
592b7800 15
f1c081b6 16#include <apt-pkg/configuration.h>
472ff00e 17#include <apt-pkg/strutl.h>
96b1e40d 18#include <apt-pkg/error.h>
01fc8930 19#include <apt-pkg/fileutl.h>
472ff00e 20
592b7800
MV
21#include <iostream>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <pwd.h>
27
28#include "netrc.h"
29
8f3ba4e8 30using std::string;
592b7800
MV
31
32/* Get user and password from .netrc when given a machine name */
33
34enum {
35 NOTHING,
36 HOSTFOUND, /* the 'machine' keyword was found */
37 HOSTCOMPLETE, /* the machine name following the keyword was found too */
38 HOSTVALID, /* this is "our" machine! */
39 HOSTEND /* LAST enum */
40};
41
42/* make sure we have room for at least this size: */
7735ad05
MV
43#define LOGINSIZE 256
44#define PASSWORDSIZE 256
592b7800
MV
45#define NETRC DOT_CHAR "netrc"
46
47/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
b8c50bd0 48static int parsenetrc_string (char *host, std::string &login, std::string &password, char *netrcfile = NULL)
592b7800
MV
49{
50 FILE *file;
51 int retcode = 1;
b8c50bd0 52 int specific_login = (login.empty() == false);
592b7800
MV
53 char *home = NULL;
54 bool netrc_alloc = false;
592b7800 55
592b7800
MV
56 int state_our_login = false; /* With specific_login,
57 found *our* login name */
58
59 if (!netrcfile) {
60 home = getenv ("HOME"); /* portable environment reader */
61
62 if (!home) {
63 struct passwd *pw;
64 pw = getpwuid (geteuid ());
65 if(pw)
66 home = pw->pw_dir;
67 }
68
69 if (!home)
70 return -1;
71
31bda500 72 if (asprintf (&netrcfile, "%s%s%s", home, DIR_CHAR, NETRC) == -1 || netrcfile == NULL)
592b7800
MV
73 return -1;
74 else
75 netrc_alloc = true;
76 }
77
78 file = fopen (netrcfile, "r");
79 if(file) {
80 char *tok;
81 char *tok_buf;
82 bool done = false;
7f18595b
DK
83 char *netrcbuffer = NULL;
84 size_t netrcbuffer_size = 0;
592b7800 85
91c03d37
DK
86 int state = NOTHING;
87 char state_login = 0; /* Found a login keyword */
88 char state_password = 0; /* Found a password keyword */
89
7f18595b 90 while (!done && getline(&netrcbuffer, &netrcbuffer_size, file) != -1) {
592b7800
MV
91 tok = strtok_r (netrcbuffer, " \t\n", &tok_buf);
92 while (!done && tok) {
b8c50bd0 93 if(login.empty() == false && password.empty() == false) {
592b7800
MV
94 done = true;
95 break;
96 }
97
98 switch(state) {
99 case NOTHING:
100 if (!strcasecmp ("machine", tok)) {
101 /* the next tok is the machine name, this is in itself the
102 delimiter that starts the stuff entered for this machine,
103 after this we need to search for 'login' and
104 'password'. */
105 state = HOSTFOUND;
106 }
107 break;
108 case HOSTFOUND:
278835da
MV
109 /* extended definition of a "machine" if we have a "/"
110 we match the start of the string (host.startswith(token) */
111 if ((strchr(host, '/') && strstr(host, tok) == host) ||
112 (!strcasecmp (host, tok))) {
592b7800
MV
113 /* and yes, this is our host! */
114 state = HOSTVALID;
115 retcode = 0; /* we did find our host */
116 }
117 else
118 /* not our host */
119 state = NOTHING;
120 break;
121 case HOSTVALID:
122 /* we are now parsing sub-keywords concerning "our" host */
123 if (state_login) {
124 if (specific_login)
b8c50bd0 125 state_our_login = !strcasecmp (login.c_str(), tok);
592b7800 126 else
b8c50bd0 127 login = tok;
592b7800
MV
128 state_login = 0;
129 } else if (state_password) {
130 if (state_our_login || !specific_login)
b8c50bd0 131 password = tok;
592b7800
MV
132 state_password = 0;
133 } else if (!strcasecmp ("login", tok))
134 state_login = 1;
135 else if (!strcasecmp ("password", tok))
136 state_password = 1;
137 else if(!strcasecmp ("machine", tok)) {
138 /* ok, there's machine here go => */
139 state = HOSTFOUND;
140 state_our_login = false;
141 }
142 break;
143 } /* switch (state) */
144
145 tok = strtok_r (NULL, " \t\n", &tok_buf);
146 } /* while(tok) */
7f18595b 147 } /* while getline() */
592b7800 148
7f18595b 149 free(netrcbuffer);
592b7800
MV
150 fclose(file);
151 }
152
153 if (netrc_alloc)
154 free(netrcfile);
155
156 return retcode;
157}
b8c50bd0
DK
158// for some unknown reason this method is exported so keep a compatible interface for now …
159int parsenetrc (char *host, char *login, char *password, char *netrcfile = NULL)
160{
161 std::string login_string, password_string;
162 int const ret = parsenetrc_string(host, login_string, password_string, netrcfile);
163 if (ret < 0)
164 return ret;
165 strncpy(login, login_string.c_str(), LOGINSIZE - 1);
166 strncpy(password, password_string.c_str(), PASSWORDSIZE - 1);
167 return ret;
168}
169
592b7800
MV
170
171void maybe_add_auth (URI &Uri, string NetRCFile)
172{
f1c081b6 173 if (_config->FindB("Debug::Acquire::netrc", false) == true)
01fc8930
MV
174 std::clog << "maybe_add_auth: " << (string)Uri
175 << " " << NetRCFile << std::endl;
f1c081b6 176 if (Uri.Password.empty () == true || Uri.User.empty () == true)
592b7800
MV
177 {
178 if (NetRCFile.empty () == false)
179 {
b8c50bd0 180 std::string login, password;
fc3eb5b2 181 char *netrcfile = strdup(NetRCFile.c_str());
592b7800 182
01fc8930 183 // first check for a generic host based netrc entry
fc3eb5b2 184 char *host = strdup(Uri.Host.c_str());
b8c50bd0 185 if (host && parsenetrc_string(host, login, password, netrcfile) == 0)
592b7800 186 {
01fc8930
MV
187 if (_config->FindB("Debug::Acquire::netrc", false) == true)
188 std::clog << "host: " << host
189 << " user: " << login
b8c50bd0 190 << " pass-size: " << password.size()
01fc8930 191 << std::endl;
b8c50bd0
DK
192 Uri.User = login;
193 Uri.Password = password;
fc3eb5b2
DK
194 free(netrcfile);
195 free(host);
01fc8930 196 return;
592b7800 197 }
fc3eb5b2 198 free(host);
592b7800 199
278835da
MV
200 // if host did not work, try Host+Path next, this will trigger
201 // a lookup uri.startswith(host) in the netrc file parser (because
202 // of the "/"
fc3eb5b2 203 char *hostpath = strdup(string(Uri.Host+Uri.Path).c_str());
b8c50bd0 204 if (hostpath && parsenetrc_string(hostpath, login, password, netrcfile) == 0)
01fc8930
MV
205 {
206 if (_config->FindB("Debug::Acquire::netrc", false) == true)
207 std::clog << "hostpath: " << hostpath
208 << " user: " << login
b8c50bd0 209 << " pass-size: " << password.size()
01fc8930 210 << std::endl;
b8c50bd0
DK
211 Uri.User = login;
212 Uri.Password = password;
01fc8930 213 }
fc3eb5b2
DK
214 free(netrcfile);
215 free(hostpath);
592b7800
MV
216 }
217 }
218}
219
220#ifdef DEBUG
221int main(int argc, char* argv[])
222{
223 char login[64] = "";
224 char password[64] = "";
225
226 if(argc < 2)
227 return -1;
228
229 if(0 == parsenetrc (argv[1], login, password, argv[2])) {
230 printf("HOST: %s LOGIN: %s PASSWORD: %s\n", argv[1], login, password);
231 }
232}
233#endif