do not pollute namespace in the headers with using (Closes: #500198)
[ntk/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>
01fc8930 17#include <apt-pkg/fileutl.h>
592b7800
MV
18#include <iostream>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <pwd.h>
24
25#include "netrc.h"
26
8f3ba4e8 27using std::string;
592b7800
MV
28
29/* Get user and password from .netrc when given a machine name */
30
31enum {
32 NOTHING,
33 HOSTFOUND, /* the 'machine' keyword was found */
34 HOSTCOMPLETE, /* the machine name following the keyword was found too */
35 HOSTVALID, /* this is "our" machine! */
36 HOSTEND /* LAST enum */
37};
38
39/* make sure we have room for at least this size: */
40#define LOGINSIZE 64
41#define PASSWORDSIZE 64
42#define NETRC DOT_CHAR "netrc"
43
44/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
45int parsenetrc (char *host, char *login, char *password, char *netrcfile = NULL)
46{
47 FILE *file;
48 int retcode = 1;
49 int specific_login = (login[0] != 0);
50 char *home = NULL;
51 bool netrc_alloc = false;
592b7800 52
592b7800
MV
53 int state_our_login = false; /* With specific_login,
54 found *our* login name */
55
56 if (!netrcfile) {
57 home = getenv ("HOME"); /* portable environment reader */
58
59 if (!home) {
60 struct passwd *pw;
61 pw = getpwuid (geteuid ());
62 if(pw)
63 home = pw->pw_dir;
64 }
65
66 if (!home)
67 return -1;
68
69 asprintf (&netrcfile, "%s%s%s", home, DIR_CHAR, NETRC);
70 if(!netrcfile)
71 return -1;
72 else
73 netrc_alloc = true;
74 }
75
76 file = fopen (netrcfile, "r");
77 if(file) {
78 char *tok;
79 char *tok_buf;
80 bool done = false;
81 char netrcbuffer[256];
82
91c03d37
DK
83 int state = NOTHING;
84 char state_login = 0; /* Found a login keyword */
85 char state_password = 0; /* Found a password keyword */
86
592b7800
MV
87 while (!done && fgets(netrcbuffer, sizeof (netrcbuffer), file)) {
88 tok = strtok_r (netrcbuffer, " \t\n", &tok_buf);
89 while (!done && tok) {
90 if(login[0] && password[0]) {
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)
122 state_our_login = !strcasecmp (login, tok);
123 else
124 strncpy (login, tok, LOGINSIZE - 1);
125 state_login = 0;
126 } else if (state_password) {
127 if (state_our_login || !specific_login)
128 strncpy (password, tok, PASSWORDSIZE - 1);
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) */
144 } /* while fgets() */
145
146 fclose(file);
147 }
148
149 if (netrc_alloc)
150 free(netrcfile);
151
152 return retcode;
153}
154
155void maybe_add_auth (URI &Uri, string NetRCFile)
156{
f1c081b6 157 if (_config->FindB("Debug::Acquire::netrc", false) == true)
01fc8930
MV
158 std::clog << "maybe_add_auth: " << (string)Uri
159 << " " << NetRCFile << std::endl;
f1c081b6 160 if (Uri.Password.empty () == true || Uri.User.empty () == true)
592b7800
MV
161 {
162 if (NetRCFile.empty () == false)
163 {
164 char login[64] = "";
165 char password[64] = "";
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());
01fc8930 170 if (host && parsenetrc (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
175 << " pass-size: " << strlen(password)
176 << std::endl;
592b7800
MV
177 Uri.User = string (login);
178 Uri.Password = string (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 "/"
fc3eb5b2 188 char *hostpath = strdup(string(Uri.Host+Uri.Path).c_str());
01fc8930
MV
189 if (hostpath && parsenetrc (hostpath, login, password, netrcfile) == 0)
190 {
191 if (_config->FindB("Debug::Acquire::netrc", false) == true)
192 std::clog << "hostpath: " << hostpath
193 << " user: " << login
194 << " pass-size: " << strlen(password)
195 << std::endl;
196 Uri.User = string (login);
197 Uri.Password = string (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