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