]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/netrc.cc
merged lp:~mvo/apt/fix-priority-abi-break
[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}
158
159void maybe_add_auth (URI &Uri, string NetRCFile)
160{
f1c081b6 161 if (_config->FindB("Debug::Acquire::netrc", false) == true)
01fc8930
MV
162 std::clog << "maybe_add_auth: " << (string)Uri
163 << " " << NetRCFile << std::endl;
f1c081b6 164 if (Uri.Password.empty () == true || Uri.User.empty () == true)
592b7800
MV
165 {
166 if (NetRCFile.empty () == false)
167 {
b8c50bd0 168 std::string login, password;
fc3eb5b2 169 char *netrcfile = strdup(NetRCFile.c_str());
592b7800 170
01fc8930 171 // first check for a generic host based netrc entry
fc3eb5b2 172 char *host = strdup(Uri.Host.c_str());
b8c50bd0 173 if (host && parsenetrc_string(host, login, password, netrcfile) == 0)
592b7800 174 {
01fc8930
MV
175 if (_config->FindB("Debug::Acquire::netrc", false) == true)
176 std::clog << "host: " << host
177 << " user: " << login
b8c50bd0 178 << " pass-size: " << password.size()
01fc8930 179 << std::endl;
b8c50bd0
DK
180 Uri.User = login;
181 Uri.Password = password;
fc3eb5b2
DK
182 free(netrcfile);
183 free(host);
01fc8930 184 return;
592b7800 185 }
fc3eb5b2 186 free(host);
592b7800 187
278835da
MV
188 // if host did not work, try Host+Path next, this will trigger
189 // a lookup uri.startswith(host) in the netrc file parser (because
190 // of the "/"
fc3eb5b2 191 char *hostpath = strdup(string(Uri.Host+Uri.Path).c_str());
b8c50bd0 192 if (hostpath && parsenetrc_string(hostpath, login, password, netrcfile) == 0)
01fc8930
MV
193 {
194 if (_config->FindB("Debug::Acquire::netrc", false) == true)
195 std::clog << "hostpath: " << hostpath
196 << " user: " << login
b8c50bd0 197 << " pass-size: " << password.size()
01fc8930 198 << std::endl;
b8c50bd0
DK
199 Uri.User = login;
200 Uri.Password = password;
01fc8930 201 }
fc3eb5b2
DK
202 free(netrcfile);
203 free(hostpath);
592b7800
MV
204 }
205 }
206}
207
208#ifdef DEBUG
209int main(int argc, char* argv[])
210{
211 char login[64] = "";
212 char password[64] = "";
213
214 if(argc < 2)
215 return -1;
216
217 if(0 == parsenetrc (argv[1], login, password, argv[2])) {
218 printf("HOST: %s LOGIN: %s PASSWORD: %s\n", argv[1], login, password);
219 }
220}
221#endif